aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/bcm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/bcm')
-rw-r--r--drivers/staging/bcm/Adapter.h457
-rw-r--r--drivers/staging/bcm/Bcmchar.c2652
-rw-r--r--drivers/staging/bcm/Bcmnet.c241
-rw-r--r--drivers/staging/bcm/CmHost.c2253
-rw-r--r--drivers/staging/bcm/CmHost.h62
-rw-r--r--drivers/staging/bcm/DDRInit.c1239
-rw-r--r--drivers/staging/bcm/DDRInit.h9
-rw-r--r--drivers/staging/bcm/Debug.h242
-rw-r--r--drivers/staging/bcm/HandleControlPacket.c235
-rw-r--r--drivers/staging/bcm/HostMIBSInterface.h192
-rw-r--r--drivers/staging/bcm/IPv6Protocol.c451
-rw-r--r--drivers/staging/bcm/IPv6ProtocolHdr.h85
-rw-r--r--drivers/staging/bcm/InterfaceAdapter.h79
-rw-r--r--drivers/staging/bcm/InterfaceDld.c316
-rw-r--r--drivers/staging/bcm/InterfaceIdleMode.c275
-rw-r--r--drivers/staging/bcm/InterfaceIdleMode.h15
-rw-r--r--drivers/staging/bcm/InterfaceInit.c717
-rw-r--r--drivers/staging/bcm/InterfaceInit.h26
-rw-r--r--drivers/staging/bcm/InterfaceIsr.c190
-rw-r--r--drivers/staging/bcm/InterfaceIsr.h15
-rw-r--r--drivers/staging/bcm/InterfaceMacros.h18
-rw-r--r--drivers/staging/bcm/InterfaceMisc.c217
-rw-r--r--drivers/staging/bcm/InterfaceMisc.h42
-rw-r--r--drivers/staging/bcm/InterfaceRx.c233
-rw-r--r--drivers/staging/bcm/InterfaceRx.h7
-rw-r--r--drivers/staging/bcm/InterfaceTx.c174
-rw-r--r--drivers/staging/bcm/InterfaceTx.h7
-rw-r--r--drivers/staging/bcm/Ioctl.h226
-rw-r--r--drivers/staging/bcm/Kconfig6
-rw-r--r--drivers/staging/bcm/LeakyBucket.c317
-rw-r--r--drivers/staging/bcm/Macros.h352
-rw-r--r--drivers/staging/bcm/Makefile12
-rw-r--r--drivers/staging/bcm/Misc.c1580
-rw-r--r--drivers/staging/bcm/PHSDefines.h94
-rw-r--r--drivers/staging/bcm/PHSModule.c1448
-rw-r--r--drivers/staging/bcm/PHSModule.h50
-rw-r--r--drivers/staging/bcm/Protocol.h128
-rw-r--r--drivers/staging/bcm/Prototypes.h222
-rw-r--r--drivers/staging/bcm/Qos.c777
-rw-r--r--drivers/staging/bcm/Queue.h31
-rw-r--r--drivers/staging/bcm/TODO22
-rw-r--r--drivers/staging/bcm/Transmit.c245
-rw-r--r--drivers/staging/bcm/Typedefs.h47
-rw-r--r--drivers/staging/bcm/cntrl_SignalingInterface.h311
-rw-r--r--drivers/staging/bcm/headers.h78
-rw-r--r--drivers/staging/bcm/hostmibs.c150
-rw-r--r--drivers/staging/bcm/led_control.c916
-rw-r--r--drivers/staging/bcm/led_control.h84
-rw-r--r--drivers/staging/bcm/nvm.c4613
-rw-r--r--drivers/staging/bcm/nvm.h286
-rw-r--r--drivers/staging/bcm/sort.c52
-rw-r--r--drivers/staging/bcm/target_params.h57
-rw-r--r--drivers/staging/bcm/vendorspecificextn.c142
-rw-r--r--drivers/staging/bcm/vendorspecificextn.h18
54 files changed, 22713 insertions, 0 deletions
diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h
new file mode 100644
index 00000000000..1b2d9f3bd55
--- /dev/null
+++ b/drivers/staging/bcm/Adapter.h
@@ -0,0 +1,457 @@
+/***********************************
+* Adapter.h
+************************************/
+#ifndef __ADAPTER_H__
+#define __ADAPTER_H__
+
+#define MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES 256
+#include "Debug.h"
+
+struct bcm_leader {
+ USHORT Vcid;
+ USHORT PLength;
+ UCHAR Status;
+ UCHAR Unused[3];
+} __packed;
+
+struct bcm_packettosend {
+ struct bcm_leader Leader;
+ UCHAR ucPayload;
+} __packed;
+
+struct bcm_control_packet {
+ PVOID ControlBuff;
+ UINT ControlBuffLen;
+ struct bcm_control_packet *next;
+} __packed;
+
+struct bcm_link_request {
+ struct bcm_leader Leader;
+ UCHAR szData[4];
+} __packed;
+
+#define MAX_IP_RANGE_LENGTH 4
+#define MAX_PORT_RANGE 4
+#define MAX_PROTOCOL_LENGTH 32
+#define IPV6_ADDRESS_SIZEINBYTES 0x10
+
+union u_ip_address {
+ struct {
+ /* Source Ip Address Range */
+ ULONG ulIpv4Addr[MAX_IP_RANGE_LENGTH];
+ /* Source Ip Mask Address Range */
+ ULONG ulIpv4Mask[MAX_IP_RANGE_LENGTH];
+ };
+ struct {
+ ULONG ulIpv6Addr[MAX_IP_RANGE_LENGTH * 4]; /* Source Ip Address Range */
+ ULONG ulIpv6Mask[MAX_IP_RANGE_LENGTH * 4]; /* Source Ip Mask Address Range */
+ };
+ struct {
+ UCHAR ucIpv4Address[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS];
+ UCHAR ucIpv4Mask[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS];
+ };
+ struct {
+ UCHAR ucIpv6Address[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
+ UCHAR ucIpv6Mask[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
+ };
+};
+
+struct bcm_hdr_suppression_contextinfo {
+ UCHAR ucaHdrSuppressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */
+ UCHAR ucaHdrSuppressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; /* Intermediate buffer containing pkt Header after PHS */
+};
+
+struct bcm_classifier_rule {
+ ULONG ulSFID;
+ UCHAR ucReserved[2];
+ B_UINT16 uiClassifierRuleIndex;
+ bool bUsed;
+ USHORT usVCID_Value;
+ B_UINT8 u8ClassifierRulePriority; /* This field detemines the Classifier Priority */
+ union u_ip_address stSrcIpAddress;
+ UCHAR ucIPSourceAddressLength; /* Ip Source Address Length */
+
+ union u_ip_address stDestIpAddress;
+ UCHAR ucIPDestinationAddressLength; /* Ip Destination Address Length */
+ UCHAR ucIPTypeOfServiceLength; /* Type of service Length */
+ UCHAR ucTosLow; /* Tos Low */
+ UCHAR ucTosHigh; /* Tos High */
+ UCHAR ucTosMask; /* Tos Mask */
+
+ UCHAR ucProtocolLength; /* protocol Length */
+ UCHAR ucProtocol[MAX_PROTOCOL_LENGTH]; /* protocol Length */
+ USHORT usSrcPortRangeLo[MAX_PORT_RANGE];
+ USHORT usSrcPortRangeHi[MAX_PORT_RANGE];
+ UCHAR ucSrcPortRangeLength;
+
+ USHORT usDestPortRangeLo[MAX_PORT_RANGE];
+ USHORT usDestPortRangeHi[MAX_PORT_RANGE];
+ UCHAR ucDestPortRangeLength;
+
+ bool bProtocolValid;
+ bool bTOSValid;
+ bool bDestIpValid;
+ bool bSrcIpValid;
+
+ /* For IPv6 Addressing */
+ UCHAR ucDirection;
+ bool bIpv6Protocol;
+ UINT32 u32PHSRuleID;
+ struct bcm_phs_rule sPhsRule;
+ UCHAR u8AssociatedPHSI;
+
+ /* Classification fields for ETH CS */
+ UCHAR ucEthCSSrcMACLen;
+ UCHAR au8EThCSSrcMAC[MAC_ADDRESS_SIZE];
+ UCHAR au8EThCSSrcMACMask[MAC_ADDRESS_SIZE];
+ UCHAR ucEthCSDestMACLen;
+ UCHAR au8EThCSDestMAC[MAC_ADDRESS_SIZE];
+ UCHAR au8EThCSDestMACMask[MAC_ADDRESS_SIZE];
+ UCHAR ucEtherTypeLen;
+ UCHAR au8EthCSEtherType[NUM_ETHERTYPE_BYTES];
+ UCHAR usUserPriority[2];
+ USHORT usVLANID;
+ USHORT usValidityBitMap;
+};
+
+struct bcm_fragmented_packet_info {
+ bool bUsed;
+ ULONG ulSrcIpAddress;
+ USHORT usIpIdentification;
+ struct bcm_classifier_rule *pstMatchedClassifierEntry;
+ bool bOutOfOrderFragment;
+};
+
+struct bcm_packet_info {
+ /* classification extension Rule */
+ ULONG ulSFID;
+ USHORT usVCID_Value;
+ UINT uiThreshold;
+ /* This field determines the priority of the SF Queues */
+ B_UINT8 u8TrafficPriority;
+
+ bool bValid;
+ bool bActive;
+ bool bActivateRequestSent;
+
+ B_UINT8 u8QueueType; /* BE or rtPS */
+
+ UINT uiMaxBucketSize; /* maximum size of the bucket for the queue */
+ UINT uiCurrentQueueDepthOnTarget;
+ UINT uiCurrentBytesOnHost;
+ UINT uiCurrentPacketsOnHost;
+ UINT uiDroppedCountBytes;
+ UINT uiDroppedCountPackets;
+ UINT uiSentBytes;
+ UINT uiSentPackets;
+ UINT uiCurrentDrainRate;
+ UINT uiThisPeriodSentBytes;
+ LARGE_INTEGER liDrainCalculated;
+ UINT uiCurrentTokenCount;
+ LARGE_INTEGER liLastUpdateTokenAt;
+ UINT uiMaxAllowedRate;
+ UINT NumOfPacketsSent;
+ UCHAR ucDirection;
+ USHORT usCID;
+ struct bcm_mibs_parameters stMibsExtServiceFlowTable;
+ UINT uiCurrentRxRate;
+ UINT uiThisPeriodRxBytes;
+ UINT uiTotalRxBytes;
+ UINT uiTotalTxBytes;
+ UINT uiPendedLast;
+ UCHAR ucIpVersion;
+
+ union {
+ struct {
+ struct sk_buff *FirstTxQueue;
+ struct sk_buff *LastTxQueue;
+ };
+ struct {
+ struct sk_buff *ControlHead;
+ struct sk_buff *ControlTail;
+ };
+ };
+
+ bool bProtocolValid;
+ bool bTOSValid;
+ bool bDestIpValid;
+ bool bSrcIpValid;
+
+ bool bActiveSet;
+ bool bAdmittedSet;
+ bool bAuthorizedSet;
+ bool bClassifierPriority;
+ UCHAR ucServiceClassName[MAX_CLASS_NAME_LENGTH];
+ bool bHeaderSuppressionEnabled;
+ spinlock_t SFQueueLock;
+ void *pstSFIndication;
+ struct timeval stLastUpdateTokenAt;
+ atomic_t uiPerSFTxResourceCount;
+ UINT uiMaxLatency;
+ UCHAR bIPCSSupport;
+ UCHAR bEthCSSupport;
+};
+
+struct bcm_tarang_data {
+ struct bcm_tarang_data *next;
+ struct bcm_mini_adapter *Adapter;
+ struct sk_buff *RxAppControlHead;
+ struct sk_buff *RxAppControlTail;
+ int AppCtrlQueueLen;
+ bool MacTracingEnabled;
+ bool bApplicationToExit;
+ struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs;
+ ULONG RxCntrlMsgBitMask;
+};
+
+struct bcm_targetdsx_buffer {
+ ULONG ulTargetDsxBuffer;
+ B_UINT16 tid;
+ bool valid;
+};
+
+typedef int (*FP_FLASH_WRITE)(struct bcm_mini_adapter *, UINT, PVOID);
+
+typedef int (*FP_FLASH_WRITE_STATUS)(struct bcm_mini_adapter *, UINT, PVOID);
+
+/*
+ * Driver adapter data structure
+ */
+struct bcm_mini_adapter {
+ struct bcm_mini_adapter *next;
+ struct net_device *dev;
+ u32 msg_enable;
+ CHAR *caDsxReqResp;
+ atomic_t ApplicationRunning;
+ bool AppCtrlQueueOverFlow;
+ atomic_t CurrentApplicationCount;
+ atomic_t RegisteredApplicationCount;
+ bool LinkUpStatus;
+ bool TimerActive;
+ u32 StatisticsPointer;
+ struct sk_buff *RxControlHead;
+ struct sk_buff *RxControlTail;
+ struct semaphore RxAppControlQueuelock;
+ struct semaphore fw_download_sema;
+ struct bcm_tarang_data *pTarangs;
+ spinlock_t control_queue_lock;
+ wait_queue_head_t process_read_wait_queue;
+
+ /* the pointer to the first packet we have queued in send
+ * deserialized miniport support variables
+ */
+ atomic_t TotalPacketCount;
+ atomic_t TxPktAvail;
+
+ /* this to keep track of the Tx and Rx MailBox Registers. */
+ atomic_t CurrNumFreeTxDesc;
+ /* to keep track the no of byte received */
+ USHORT PrevNumRecvDescs;
+ USHORT CurrNumRecvDescs;
+ UINT u32TotalDSD;
+ struct bcm_packet_info PackInfo[NO_OF_QUEUES];
+ struct bcm_classifier_rule astClassifierTable[MAX_CLASSIFIERS];
+ bool TransferMode;
+
+ /*************** qos ******************/
+ bool bETHCSEnabled;
+ ULONG BEBucketSize;
+ ULONG rtPSBucketSize;
+ UCHAR LinkStatus;
+ bool AutoLinkUp;
+ bool AutoSyncup;
+
+ int major;
+ int minor;
+ wait_queue_head_t tx_packet_wait_queue;
+ wait_queue_head_t process_rx_cntrlpkt;
+ atomic_t process_waiting;
+ bool fw_download_done;
+
+ char *txctlpacket[MAX_CNTRL_PKTS];
+ atomic_t cntrlpktCnt;
+ atomic_t index_app_read_cntrlpkt;
+ atomic_t index_wr_txcntrlpkt;
+ atomic_t index_rd_txcntrlpkt;
+ UINT index_datpkt;
+ struct semaphore rdmwrmsync;
+
+ struct bcm_targetdsx_buffer astTargetDsxBuffer[MAX_TARGET_DSX_BUFFERS];
+ ULONG ulFreeTargetBufferCnt;
+ ULONG ulCurrentTargetBuffer;
+ ULONG ulTotalTargetBuffersAvailable;
+ unsigned long chip_id;
+ wait_queue_head_t lowpower_mode_wait_queue;
+ bool bFlashBoot;
+ bool bBinDownloaded;
+ bool bCfgDownloaded;
+ bool bSyncUpRequestSent;
+ USHORT usBestEffortQueueIndex;
+ wait_queue_head_t ioctl_fw_dnld_wait_queue;
+ bool waiting_to_fw_download_done;
+ pid_t fw_download_process_pid;
+ struct bcm_target_params *pstargetparams;
+ bool device_removed;
+ bool DeviceAccess;
+ bool bIsAutoCorrectEnabled;
+ bool bDDRInitDone;
+ int DDRSetting;
+ ULONG ulPowerSaveMode;
+ spinlock_t txtransmitlock;
+ B_UINT8 txtransmit_running;
+ /* Thread for control packet handling */
+ struct task_struct *control_packet_handler;
+ /* thread for transmitting packets. */
+ struct task_struct *transmit_packet_thread;
+
+ /* LED Related Structures */
+ struct bcm_led_info LEDInfo;
+
+ /* Driver State for LED Blinking */
+ enum bcm_led_events DriverState;
+ /* Interface Specific */
+ PVOID pvInterfaceAdapter;
+ int (*bcm_file_download)(PVOID,
+ struct file *,
+ unsigned int);
+ int (*bcm_file_readback_from_chip)(PVOID,
+ struct file *,
+ unsigned int);
+ int (*interface_rdm)(PVOID,
+ UINT,
+ PVOID,
+ int);
+ int (*interface_wrm)(PVOID,
+ UINT,
+ PVOID,
+ int);
+ int (*interface_transmit)(PVOID, PVOID , UINT);
+ bool IdleMode;
+ bool bDregRequestSentInIdleMode;
+ bool bTriedToWakeUpFromlowPowerMode;
+ bool bShutStatus;
+ bool bWakeUpDevice;
+ unsigned int usIdleModePattern;
+ /* BOOLEAN bTriedToWakeUpFromShutdown; */
+ bool bLinkDownRequested;
+ int downloadDDR;
+ struct bcm_phs_extension stBCMPhsContext;
+ struct bcm_hdr_suppression_contextinfo stPhsTxContextInfo;
+ uint8_t ucaPHSPktRestoreBuf[2048];
+ uint8_t bPHSEnabled;
+ bool AutoFirmDld;
+ bool bMipsConfig;
+ bool bDPLLConfig;
+ UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
+ UINT32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
+ struct bcm_fragmented_packet_info astFragmentedPktClassifierTable[MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES];
+ atomic_t uiMBupdate;
+ UINT32 PmuMode;
+ enum bcm_nvm_type eNVMType;
+ UINT uiSectorSize;
+ UINT uiSectorSizeInCFG;
+ bool bSectorSizeOverride;
+ bool bStatusWrite;
+ UINT uiNVMDSDSize;
+ UINT uiVendorExtnFlag;
+ /* it will always represent chosen DSD at any point of time.
+ * Generally it is Active DSD but in case of NVM RD/WR it might be different.
+ */
+ UINT ulFlashCalStart;
+ ULONG ulFlashControlSectionStart;
+ ULONG ulFlashWriteSize;
+ ULONG ulFlashID;
+ FP_FLASH_WRITE fpFlashWrite;
+ FP_FLASH_WRITE_STATUS fpFlashWriteWithStatusCheck;
+
+ struct semaphore NVMRdmWrmLock;
+ struct device *pstCreatedClassDevice;
+
+ /* BOOLEAN InterfaceUpStatus; */
+ struct bcm_flash2x_cs_info *psFlash2xCSInfo;
+ struct bcm_flash_cs_info *psFlashCSInfo;
+ struct bcm_flash2x_vendor_info *psFlash2xVendorInfo;
+ UINT uiFlashBaseAdd; /* Flash start address */
+ UINT uiActiveISOOffset; /* Active ISO offset chosen before f/w download */
+ enum bcm_flash2x_section_val eActiveISO; /* Active ISO section val */
+ enum bcm_flash2x_section_val eActiveDSD; /* Active DSD val chosen before f/w download */
+ UINT uiActiveDSDOffsetAtFwDld; /* For accessing Active DSD chosen before f/w download */
+ UINT uiFlashLayoutMajorVersion;
+ UINT uiFlashLayoutMinorVersion;
+ bool bAllDSDWriteAllow;
+ bool bSigCorrupted;
+ /* this should be set who so ever want to change the Headers. after Write it should be reset immediately. */
+ bool bHeaderChangeAllowed;
+ int SelectedChip;
+ bool bEndPointHalted;
+ /* while bFlashRawRead will be true, Driver ignore map lay out and consider flash as of without any map. */
+ bool bFlashRawRead;
+ bool bPreparingForLowPowerMode;
+ bool bDoSuspend;
+ UINT syscfgBefFwDld;
+ bool StopAllXaction;
+ UINT32 liTimeSinceLastNetEntry; /* Used to Support extended CAPI requirements from */
+ struct semaphore LowPowerModeSync;
+ ULONG liDrainCalculated;
+ UINT gpioBitMap;
+ struct bcm_debug_state stDebugState;
+};
+
+#define GET_BCM_ADAPTER(net_dev) netdev_priv(net_dev)
+
+struct bcm_eth_header {
+ UCHAR au8DestinationAddress[6];
+ UCHAR au8SourceAddress[6];
+ USHORT u16Etype;
+} __packed;
+
+struct bcm_firmware_info {
+ void __user *pvMappedFirmwareAddress;
+ ULONG u32FirmwareLength;
+ ULONG u32StartingAddress;
+} __packed;
+
+/* holds the value of net_device structure.. */
+extern struct net_device *gblpnetdev;
+
+struct bcm_ddr_setting {
+ UINT ulRegAddress;
+ UINT ulRegValue;
+};
+int InitAdapter(struct bcm_mini_adapter *psAdapter);
+
+/* =====================================================================
+ * Beceem vendor request codes for EP0
+ * =====================================================================
+ */
+
+#define BCM_REQUEST_READ 0x2
+#define BCM_REQUEST_WRITE 0x1
+#define EP2_MPS_REG 0x0F0110A0
+#define EP2_MPS 0x40
+
+#define EP2_CFG_REG 0x0F0110A8
+#define EP2_CFG_INT 0x27
+#define EP2_CFG_BULK 0x25
+
+#define EP4_MPS_REG 0x0F0110F0
+#define EP4_MPS 0x8C
+
+#define EP4_CFG_REG 0x0F0110F8
+
+#define ISO_MPS_REG 0x0F0110C8
+#define ISO_MPS 0x00000000
+
+#define EP1 0
+#define EP2 1
+#define EP3 2
+#define EP4 3
+#define EP5 4
+#define EP6 5
+
+enum bcm_einterface_setting {
+ DEFAULT_SETTING_0 = 0,
+ ALTERNATE_SETTING_1 = 1,
+};
+
+#endif /* __ADAPTER_H__ */
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
new file mode 100644
index 00000000000..606d5f5e921
--- /dev/null
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -0,0 +1,2652 @@
+#include <linux/fs.h>
+
+#include "headers.h"
+
+static int bcm_handle_nvm_read_cmd(struct bcm_mini_adapter *Adapter,
+ PUCHAR pReadData, struct bcm_nvm_readwrite *stNVMReadWrite)
+{
+ INT Status = STATUS_FAILURE;
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return -EACCES;
+ }
+
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadData,
+ stNVMReadWrite->uiOffset,
+ stNVMReadWrite->uiNumBytes);
+ up(&Adapter->NVMRdmWrmLock);
+
+ if (Status != STATUS_SUCCESS) {
+ kfree(pReadData);
+ return Status;
+ }
+
+ if (copy_to_user(stNVMReadWrite->pBuffer, pReadData,
+ stNVMReadWrite->uiNumBytes)) {
+ kfree(pReadData);
+ return -EFAULT;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static int handle_flash2x_adapter(struct bcm_mini_adapter *Adapter,
+ PUCHAR pReadData, struct bcm_nvm_readwrite *stNVMReadWrite)
+{
+ /*
+ * New Requirement:-
+ * DSD section updation will be allowed in two case:-
+ * 1. if DSD sig is present in DSD header means dongle
+ * is ok and updation is fruitfull
+ * 2. if point 1 failes then user buff should have
+ * DSD sig. this point ensures that if dongle is
+ * corrupted then user space program first modify
+ * the DSD header with valid DSD sig so that this
+ * as well as further write may be worthwhile.
+ *
+ * This restriction has been put assuming that
+ * if DSD sig is corrupted, DSD data won't be
+ * considered valid.
+ */
+ INT Status;
+ ULONG ulDSDMagicNumInUsrBuff = 0;
+
+ Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD);
+ if (Status == STATUS_SUCCESS)
+ return STATUS_SUCCESS;
+
+ if (((stNVMReadWrite->uiOffset + stNVMReadWrite->uiNumBytes) !=
+ Adapter->uiNVMDSDSize) ||
+ (stNVMReadWrite->uiNumBytes < SIGNATURE_SIZE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return Status;
+ }
+
+ ulDSDMagicNumInUsrBuff =
+ ntohl(*(PUINT)(pReadData + stNVMReadWrite->uiNumBytes -
+ SIGNATURE_SIZE));
+ if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/***************************************************************
+* Function - bcm_char_open()
+*
+* Description - This is the "open" entry point for the character
+* driver.
+*
+* Parameters - inode: Pointer to the Inode structure of char device
+* filp : File pointer of the char device
+*
+* Returns - Zero(Success)
+****************************************************************/
+
+static int bcm_char_open(struct inode *inode, struct file *filp)
+{
+ struct bcm_mini_adapter *Adapter = NULL;
+ struct bcm_tarang_data *pTarang = NULL;
+
+ Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ pTarang = kzalloc(sizeof(struct bcm_tarang_data), GFP_KERNEL);
+ if (!pTarang)
+ return -ENOMEM;
+
+ pTarang->Adapter = Adapter;
+ pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB);
+
+ down(&Adapter->RxAppControlQueuelock);
+ pTarang->next = Adapter->pTarangs;
+ Adapter->pTarangs = pTarang;
+ up(&Adapter->RxAppControlQueuelock);
+
+ /* Store the Adapter structure */
+ filp->private_data = pTarang;
+
+ /* Start Queuing the control response Packets */
+ atomic_inc(&Adapter->ApplicationRunning);
+
+ nonseekable_open(inode, filp);
+ return 0;
+}
+
+static int bcm_char_release(struct inode *inode, struct file *filp)
+{
+ struct bcm_tarang_data *pTarang, *tmp, *ptmp;
+ struct bcm_mini_adapter *Adapter = NULL;
+ struct sk_buff *pkt, *npkt;
+
+ pTarang = (struct bcm_tarang_data *)filp->private_data;
+
+ if (pTarang == NULL)
+ return 0;
+
+ Adapter = pTarang->Adapter;
+
+ down(&Adapter->RxAppControlQueuelock);
+
+ tmp = Adapter->pTarangs;
+ for (ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next) {
+ if (tmp == pTarang)
+ break;
+ }
+
+ if (tmp) {
+ if (!ptmp)
+ Adapter->pTarangs = tmp->next;
+ else
+ ptmp->next = tmp->next;
+ } else {
+ up(&Adapter->RxAppControlQueuelock);
+ return 0;
+ }
+
+ pkt = pTarang->RxAppControlHead;
+ while (pkt) {
+ npkt = pkt->next;
+ kfree_skb(pkt);
+ pkt = npkt;
+ }
+
+ up(&Adapter->RxAppControlQueuelock);
+
+ /* Stop Queuing the control response Packets */
+ atomic_dec(&Adapter->ApplicationRunning);
+
+ kfree(pTarang);
+
+ /* remove this filp from the asynchronously notified filp's */
+ filp->private_data = NULL;
+ return 0;
+}
+
+static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
+ loff_t *f_pos)
+{
+ struct bcm_tarang_data *pTarang = filp->private_data;
+ struct bcm_mini_adapter *Adapter = pTarang->Adapter;
+ struct sk_buff *Packet = NULL;
+ ssize_t PktLen = 0;
+ int wait_ret_val = 0;
+ unsigned long ret = 0;
+
+ wait_ret_val = wait_event_interruptible(
+ Adapter->process_read_wait_queue,
+ (pTarang->RxAppControlHead ||
+ Adapter->device_removed));
+
+ if ((wait_ret_val == -ERESTARTSYS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Exiting as i've been asked to exit!!!\n");
+ return wait_ret_val;
+ }
+
+ if (Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device Removed... Killing the Apps...\n");
+ return -ENODEV;
+ }
+
+ if (false == Adapter->fw_download_done)
+ return -EACCES;
+
+ down(&Adapter->RxAppControlQueuelock);
+
+ if (pTarang->RxAppControlHead) {
+ Packet = pTarang->RxAppControlHead;
+ DEQUEUEPACKET(pTarang->RxAppControlHead,
+ pTarang->RxAppControlTail);
+ pTarang->AppCtrlQueueLen--;
+ }
+
+ up(&Adapter->RxAppControlQueuelock);
+
+ if (Packet) {
+ PktLen = Packet->len;
+ ret = copy_to_user(buf, Packet->data,
+ min_t(size_t, PktLen, size));
+ if (ret) {
+ dev_kfree_skb(Packet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Returning from copy to user failure\n");
+ return -EFAULT;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Read %zd Bytes From Adapter packet = %p by process %d!\n",
+ PktLen, Packet, current->pid);
+ dev_kfree_skb(Packet);
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<\n");
+ return PktLen;
+}
+
+static int bcm_char_ioctl_reg_read_private(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_rdm_buffer sRdmBuffer = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ PCHAR temp_buff;
+ INT Status = STATUS_FAILURE;
+ UINT Bufflen;
+ u16 temp_value;
+ int bytes;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+ return -EINVAL;
+
+ if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength > USHRT_MAX ||
+ IoBuffer.OutputLength == 0) {
+ return -EINVAL;
+ }
+
+ Bufflen = IoBuffer.OutputLength;
+ temp_value = 4 - (Bufflen % 4);
+ Bufflen += temp_value % 4;
+
+ temp_buff = kmalloc(Bufflen, GFP_KERNEL);
+ if (!temp_buff)
+ return -ENOMEM;
+
+ bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
+ (PUINT)temp_buff, Bufflen);
+ if (bytes > 0) {
+ Status = STATUS_SUCCESS;
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
+ kfree(temp_buff);
+ return -EFAULT;
+ }
+ } else {
+ Status = bytes;
+ }
+
+ kfree(temp_buff);
+ return Status;
+}
+
+static int bcm_char_ioctl_reg_write_private(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_wrm_buffer sWrmBuffer = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ UINT uiTempVar = 0;
+ INT Status;
+
+ /* Copy Ioctl Buffer structure */
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+ return -EINVAL;
+
+ /* Get WrmBuffer structure */
+ if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4))) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "EEPROM Access Denied, not in VSG Mode\n");
+ return -EFAULT;
+ }
+
+ Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sizeof(ULONG));
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "WRM Done\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_eeprom_reg_read(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_rdm_buffer sRdmBuffer = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ PCHAR temp_buff = NULL;
+ UINT uiTempVar = 0;
+ INT Status;
+ int bytes;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Device in Idle Mode, Blocking Rdms\n");
+ return -EACCES;
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+ return -EINVAL;
+
+ if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength > USHRT_MAX ||
+ IoBuffer.OutputLength == 0) {
+ return -EINVAL;
+ }
+
+ temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
+ if (!temp_buff)
+ return STATUS_FAILURE;
+
+ if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+ ((ULONG)sRdmBuffer.Register & 0x3)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "RDM Done On invalid Address : %x Access Denied.\n",
+ (int)sRdmBuffer.Register);
+
+ kfree(temp_buff);
+ return -EINVAL;
+ }
+
+ uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
+ bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register,
+ (PUINT)temp_buff, IoBuffer.OutputLength);
+
+ if (bytes > 0) {
+ Status = STATUS_SUCCESS;
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) {
+ kfree(temp_buff);
+ return -EFAULT;
+ }
+ } else {
+ Status = bytes;
+ }
+
+ kfree(temp_buff);
+ return Status;
+}
+
+static int bcm_char_ioctl_eeprom_reg_write(void __user *argp,
+ struct bcm_mini_adapter *Adapter,
+ UINT cmd)
+{
+ struct bcm_wrm_buffer sWrmBuffer = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ UINT uiTempVar = 0;
+ INT Status;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Device in Idle Mode, Blocking Wrms\n");
+ return -EACCES;
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+ return -EINVAL;
+
+ /* Get WrmBuffer structure */
+ if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+ ((ULONG)sWrmBuffer.Register & 0x3)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM Done On invalid Address : %x Access Denied.\n",
+ (int)sWrmBuffer.Register);
+ return -EINVAL;
+ }
+
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)) &&
+ (cmd == IOCTL_BCM_REGISTER_WRITE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "EEPROM Access Denied, not in VSG Mode\n");
+ return -EFAULT;
+ }
+
+ Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data,
+ sWrmBuffer.Length);
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG,
+ DBG_LVL_ALL, "WRM Done\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_gpio_set_request(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_gpio_info gpio_info = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ UCHAR ucResetValue[4];
+ UINT value = 0;
+ UINT uiBit = 0;
+ UINT uiOperation = 0;
+ INT Status;
+ int bytes;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "GPIO Can't be set/clear in Low power Mode");
+ return -EACCES;
+ }
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_info))
+ return -EINVAL;
+
+ if (copy_from_user(&gpio_info, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiBit = gpio_info.uiGpioNumber;
+ uiOperation = gpio_info.uiGpioValue;
+ value = (1<<uiBit);
+
+ if (IsReqGpioIsLedInNVM(Adapter, value) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",
+ value);
+ return -EINVAL;
+ }
+
+ /* Set - setting 1 */
+ if (uiOperation) {
+ /* Set the gpio output register */
+ Status = wrmaltWithLock(Adapter,
+ BCM_GPIO_OUTPUT_SET_REG,
+ (PUINT)(&value), sizeof(UINT));
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL,
+ "Set the GPIO bit\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL,
+ "Failed to set the %dth GPIO\n",
+ uiBit);
+ return Status;
+ }
+ } else {
+ /* Set the gpio output register */
+ Status = wrmaltWithLock(Adapter,
+ BCM_GPIO_OUTPUT_CLR_REG,
+ (PUINT)(&value), sizeof(UINT));
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL,
+ "Set the GPIO bit\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL,
+ "Failed to clear the %dth GPIO\n",
+ uiBit);
+ return Status;
+ }
+ }
+
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
+ (PUINT)ucResetValue, sizeof(UINT));
+ if (bytes < 0) {
+ Status = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "GPIO_MODE_REGISTER read failed");
+ return Status;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Set the gpio mode register to output */
+ *(UINT *)ucResetValue |= (1<<uiBit);
+ Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
+ (PUINT)ucResetValue, sizeof(UINT));
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "Set the GPIO to output Mode\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "Failed to put GPIO in Output Mode\n");
+ }
+
+ return Status;
+}
+
+static int bcm_char_ioctl_led_thread_state_change_req(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_user_thread_req threadReq = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "User made LED thread InActive");
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "GPIO Can't be set/clear in Low power Mode");
+ return -EACCES;
+ }
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(threadReq))
+ return -EINVAL;
+
+ if (copy_from_user(&threadReq, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ /* if LED thread is running(Actively or Inactively)
+ * set it state to make inactive
+ */
+ if (Adapter->LEDInfo.led_thread_running) {
+ if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL,
+ "Activating thread req");
+ Adapter->DriverState = LED_THREAD_ACTIVE;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL,
+ "DeActivating Thread req.....");
+ Adapter->DriverState = LED_THREAD_INACTIVE;
+ }
+
+ /* signal thread. */
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_gpio_status_request(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_gpio_info gpio_info = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ ULONG uiBit = 0;
+ UCHAR ucRead[4];
+ INT Status;
+ int bytes;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EACCES;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_info))
+ return -EINVAL;
+
+ if (copy_from_user(&gpio_info, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiBit = gpio_info.uiGpioNumber;
+
+ /* Set the gpio output register */
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+ (PUINT)ucRead, sizeof(UINT));
+
+ if (bytes < 0) {
+ Status = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "RDM Failed\n");
+ return Status;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_gpio_multi_request(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX];
+ struct bcm_gpio_multi_info *pgpio_multi_info =
+ (struct bcm_gpio_multi_info *)gpio_multi_info;
+ struct bcm_ioctl_buffer IoBuffer;
+ UCHAR ucResetValue[4];
+ INT Status = STATUS_FAILURE;
+ int bytes;
+
+ memset(pgpio_multi_info, 0,
+ MAX_IDX * sizeof(struct bcm_gpio_multi_info));
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EINVAL;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_multi_info))
+ return -EINVAL;
+ if (IoBuffer.OutputLength > sizeof(gpio_multi_info))
+ IoBuffer.OutputLength = sizeof(gpio_multi_info);
+
+ if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask)
+ == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask,
+ Adapter->gpioBitMap);
+ return -EINVAL;
+ }
+
+ /* Set the gpio output register */
+ if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
+ (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
+ /* Set 1's in GPIO OUTPUT REGISTER */
+ *(UINT *)ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
+
+ if (*(UINT *) ucResetValue)
+ Status = wrmaltWithLock(Adapter,
+ BCM_GPIO_OUTPUT_SET_REG,
+ (PUINT)ucResetValue, sizeof(ULONG));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
+ return Status;
+ }
+
+ /* Clear to 0's in GPIO OUTPUT REGISTER */
+ *(UINT *)ucResetValue =
+ (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
+
+ if (*(UINT *) ucResetValue)
+ Status = wrmaltWithLock(Adapter,
+ BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue,
+ sizeof(ULONG));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
+ return Status;
+ }
+ }
+
+ if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+ (PUINT)ucResetValue, sizeof(UINT));
+
+ if (bytes < 0) {
+ Status = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "RDM to GPIO_PIN_STATE_REGISTER Failed.");
+ return Status;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
+
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue =
+ (*(UINT *)ucResetValue &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
+ }
+
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info,
+ IoBuffer.OutputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed while copying Content to IOBufer for user space err:%d",
+ Status);
+ return -EFAULT;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_gpio_mode_request(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX];
+ struct bcm_gpio_multi_mode *pgpio_multi_mode =
+ (struct bcm_gpio_multi_mode *)gpio_multi_mode;
+ struct bcm_ioctl_buffer IoBuffer;
+ UCHAR ucResetValue[4];
+ INT Status;
+ int bytes;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EINVAL;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
+ return -EINVAL;
+ if (IoBuffer.OutputLength > sizeof(gpio_multi_mode))
+ IoBuffer.OutputLength = sizeof(gpio_multi_mode);
+
+ if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer,
+ IoBuffer.InputLength))
+ return -EFAULT;
+
+ bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
+ (PUINT)ucResetValue, sizeof(UINT));
+
+ if (bytes < 0) {
+ Status = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Read of GPIO_MODE_REGISTER failed");
+ return Status;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Validating the request */
+ if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)
+ == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,
+ Adapter->gpioBitMap);
+ return -EINVAL;
+ }
+
+ if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
+ /* write all OUT's (1's) */
+ *(UINT *) ucResetValue |=
+ (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* write all IN's (0's) */
+ *(UINT *) ucResetValue &=
+ ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* Currently implemented return the modes of all GPIO's
+ * else needs to bit AND with mask
+ */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+
+ Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
+ (PUINT)ucResetValue, sizeof(ULONG));
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "WRM to GPIO_MODE_REGISTER Done");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM to GPIO_MODE_REGISTER Failed");
+ return -EFAULT;
+ }
+ } else {
+ /* if uiGPIOMask is 0 then return mode register configuration */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+ }
+
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode,
+ IoBuffer.OutputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed while copying Content to IOBufer for user space err:%d",
+ Status);
+ return -EFAULT;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_misc_request(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ PVOID pvBuffer = NULL;
+ INT Status;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength < sizeof(struct bcm_link_request))
+ return -EINVAL;
+
+ if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE)
+ return -EINVAL;
+
+ pvBuffer = memdup_user(IoBuffer.InputBuffer,
+ IoBuffer.InputLength);
+ if (IS_ERR(pvBuffer))
+ return PTR_ERR(pvBuffer);
+
+ down(&Adapter->LowPowerModeSync);
+ Status = wait_event_interruptible_timeout(
+ Adapter->lowpower_mode_wait_queue,
+ !Adapter->bPreparingForLowPowerMode,
+ (1 * HZ));
+
+ if (Status == -ERESTARTSYS)
+ goto cntrlEnd;
+
+ if (Adapter->bPreparingForLowPowerMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Preparing Idle Mode is still True - Hence Rejecting control message\n");
+ Status = STATUS_FAILURE;
+ goto cntrlEnd;
+ }
+ Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
+
+cntrlEnd:
+ up(&Adapter->LowPowerModeSync);
+ kfree(pvBuffer);
+ return Status;
+}
+
+static int bcm_char_ioctl_buffer_download_start(
+ struct bcm_mini_adapter *Adapter)
+{
+ INT Status;
+
+ if (down_trylock(&Adapter->NVMRdmWrmLock)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Starting the firmware download PID =0x%x!!!!\n",
+ current->pid);
+
+ if (down_trylock(&Adapter->fw_download_sema))
+ return -EBUSY;
+
+ Adapter->bBinDownloaded = false;
+ Adapter->fw_download_process_pid = current->pid;
+ Adapter->bCfgDownloaded = false;
+ Adapter->fw_download_done = false;
+ netif_carrier_off(Adapter->dev);
+ netif_stop_queue(Adapter->dev);
+ Status = reset_card_proc(Adapter);
+ if (Status) {
+ pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+ }
+ mdelay(10);
+
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+}
+
+static int bcm_char_ioctl_buffer_download(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_firmware_info *psFwInfo = NULL;
+ struct bcm_ioctl_buffer IoBuffer;
+ INT Status;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Invalid way to download buffer. Use Start and then call this!!!\n");
+ up(&Adapter->fw_download_sema);
+ return -EINVAL;
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
+ up(&Adapter->fw_download_sema);
+ return -EFAULT;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length for FW DLD is : %lx\n", IoBuffer.InputLength);
+
+ if (IoBuffer.InputLength > sizeof(struct bcm_firmware_info)) {
+ up(&Adapter->fw_download_sema);
+ return -EINVAL;
+ }
+
+ psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
+ if (!psFwInfo) {
+ up(&Adapter->fw_download_sema);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(psFwInfo, IoBuffer.InputBuffer,
+ IoBuffer.InputLength)) {
+ up(&Adapter->fw_download_sema);
+ kfree(psFwInfo);
+ return -EFAULT;
+ }
+
+ if (!psFwInfo->pvMappedFirmwareAddress ||
+ (psFwInfo->u32FirmwareLength == 0)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Something else is wrong %lu\n",
+ psFwInfo->u32FirmwareLength);
+ up(&Adapter->fw_download_sema);
+ kfree(psFwInfo);
+ Status = -EINVAL;
+ return Status;
+ }
+
+ Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
+
+ if (Status != STATUS_SUCCESS) {
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "IOCTL: Configuration File Upload Failed\n");
+ else
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "IOCTL: Firmware File Upload Failed\n");
+
+ /* up(&Adapter->fw_download_sema); */
+
+ if (Adapter->LEDInfo.led_thread_running &
+ BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = DRIVER_INIT;
+ Adapter->LEDInfo.bLedInitDone = false;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+ }
+
+ if (Status != STATUS_SUCCESS)
+ up(&Adapter->fw_download_sema);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL: Firmware File Uploaded\n");
+ kfree(psFwInfo);
+ return Status;
+}
+
+static int bcm_char_ioctl_buffer_download_stop(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ INT Status;
+ int timeout = 0;
+
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ up(&Adapter->fw_download_sema);
+ return -EINVAL;
+ }
+
+ if (down_trylock(&Adapter->NVMRdmWrmLock)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "FW download blocked as EEPROM Read/Write is in progress\n");
+ up(&Adapter->fw_download_sema);
+ return -EACCES;
+ }
+
+ Adapter->bBinDownloaded = TRUE;
+ Adapter->bCfgDownloaded = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->downloadDDR = 0;
+
+ /* setting the Mips to Run */
+ Status = run_card_proc(Adapter);
+
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Firm Download Failed\n");
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "Firm Download Over...\n");
+ }
+
+ mdelay(10);
+
+ /* Wait for MailBox Interrupt */
+ if (StartInterruptUrb((struct bcm_interface_adapter *)Adapter->pvInterfaceAdapter))
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Unable to send interrupt...\n");
+
+ timeout = 5*HZ;
+ Adapter->waiting_to_fw_download_done = false;
+ wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
+ Adapter->waiting_to_fw_download_done, timeout);
+ Adapter->fw_download_process_pid = INVALID_PID;
+ Adapter->fw_download_done = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+
+ if (Adapter->LEDInfo.led_thread_running &
+ BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = FW_DOWNLOAD_DONE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ if (!timeout)
+ Status = -ENODEV;
+
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+}
+
+static int bcm_char_ioctl_chip_reset(struct bcm_mini_adapter *Adapter)
+{
+ INT Status;
+ INT NVMAccess;
+
+ NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+
+ down(&Adapter->RxAppControlQueuelock);
+ Status = reset_card_proc(Adapter);
+ flushAllAppQ();
+ up(&Adapter->RxAppControlQueuelock);
+ up(&Adapter->NVMRdmWrmLock);
+ ResetCounters(Adapter);
+ return Status;
+}
+
+static int bcm_char_ioctl_qos_threshold(ULONG arg,
+ struct bcm_mini_adapter *Adapter)
+{
+ USHORT uiLoopIndex;
+
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+ if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
+ (unsigned long __user *)arg)) {
+ return -EFAULT;
+ }
+ }
+ return 0;
+}
+
+static int bcm_char_ioctl_switch_transfer_mode(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ UINT uiData = 0;
+
+ if (copy_from_user(&uiData, argp, sizeof(UINT)))
+ return -EFAULT;
+
+ if (uiData) {
+ /* Allow All Packets */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
+ Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
+ } else {
+ /* Allow IP only Packets */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
+ }
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_get_driver_version(void __user *argp)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ ulong len;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ len = min_t(ulong, IoBuffer.OutputLength, strlen(DRV_VERSION) + 1);
+
+ if (copy_to_user(IoBuffer.OutputBuffer, DRV_VERSION, len))
+ return -EFAULT;
+
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_get_current_status(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_link_state link_state;
+ struct bcm_ioctl_buffer IoBuffer;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "copy_from_user failed..\n");
+ return -EFAULT;
+ }
+
+ if (IoBuffer.OutputLength != sizeof(link_state))
+ return -EINVAL;
+
+ memset(&link_state, 0, sizeof(link_state));
+ link_state.bIdleMode = Adapter->IdleMode;
+ link_state.bShutdownMode = Adapter->bShutStatus;
+ link_state.ucLinkStatus = Adapter->LinkStatus;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t,
+ sizeof(link_state), IoBuffer.OutputLength))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy_to_user Failed..\n");
+ return -EFAULT;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+static int bcm_char_ioctl_set_mac_tracing(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ UINT tracing_flag;
+
+ /* copy ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
+ return -EFAULT;
+
+ if (tracing_flag)
+ Adapter->pTarangs->MacTracingEnabled = TRUE;
+ else
+ Adapter->pTarangs->MacTracingEnabled = false;
+
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_get_dsx_indication(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ ULONG ulSFId = 0;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(struct bcm_add_indication_alt)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Mismatch req: %lx needed is =0x%zx!!!",
+ IoBuffer.OutputLength,
+ sizeof(struct bcm_add_indication_alt));
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
+ return -EFAULT;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Get DSX Data SF ID is =%lx\n", ulSFId);
+ get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_get_host_mibs(void __user *argp,
+ struct bcm_mini_adapter *Adapter, struct bcm_tarang_data *pTarang)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ INT Status = STATUS_FAILURE;
+ PVOID temp_buff;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength != sizeof(struct bcm_host_stats_mibs)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length Check failed %lu %zd\n", IoBuffer.OutputLength,
+ sizeof(struct bcm_host_stats_mibs));
+ return -EINVAL;
+ }
+
+ /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
+ temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL);
+ if (!temp_buff)
+ return STATUS_FAILURE;
+
+ Status = ProcessGetHostMibs(Adapter, temp_buff);
+ GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
+
+ if (Status != STATUS_FAILURE) {
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff,
+ sizeof(struct bcm_host_stats_mibs))) {
+ kfree(temp_buff);
+ return -EFAULT;
+ }
+ }
+
+ kfree(temp_buff);
+ return Status;
+}
+
+static int bcm_char_ioctl_bulk_wrm(void __user *argp,
+ struct bcm_mini_adapter *Adapter, UINT cmd)
+{
+ struct bcm_bulk_wrm_buffer *pBulkBuffer;
+ struct bcm_ioctl_buffer IoBuffer;
+ UINT uiTempVar = 0;
+ INT Status = STATUS_FAILURE;
+ PCHAR pvBuffer = NULL;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Device in Idle/Shutdown Mode, Blocking Wrms\n");
+ return -EACCES;
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength < sizeof(ULONG) * 2)
+ return -EINVAL;
+
+ pvBuffer = memdup_user(IoBuffer.InputBuffer,
+ IoBuffer.InputLength);
+ if (IS_ERR(pvBuffer))
+ return PTR_ERR(pvBuffer);
+
+ pBulkBuffer = (struct bcm_bulk_wrm_buffer *)pvBuffer;
+
+ if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
+ ((ULONG)pBulkBuffer->Register & 0x3)) {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM Done On invalid Address : %x Access Denied.\n",
+ (int)pBulkBuffer->Register);
+ kfree(pvBuffer);
+ return -EINVAL;
+ }
+
+ uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)) &&
+ (cmd == IOCTL_BCM_REGISTER_WRITE)) {
+
+ kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "EEPROM Access Denied, not in VSG Mode\n");
+ return -EFAULT;
+ }
+
+ if (pBulkBuffer->SwapEndian == false)
+ Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register,
+ (PCHAR)pBulkBuffer->Values,
+ IoBuffer.InputLength - 2*sizeof(ULONG));
+ else
+ Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register,
+ (PUINT)pBulkBuffer->Values,
+ IoBuffer.InputLength - 2*sizeof(ULONG));
+
+ if (Status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
+
+ kfree(pvBuffer);
+ return Status;
+}
+
+static int bcm_char_ioctl_get_nvm_size(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize,
+ sizeof(UINT)))
+ return -EFAULT;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_cal_init(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ UINT uiSectorSize = 0;
+ INT Status = STATUS_FAILURE;
+
+ if (Adapter->eNVMType == NVM_FLASH) {
+ if (copy_from_user(&IoBuffer, argp,
+ sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer,
+ sizeof(UINT)))
+ return -EFAULT;
+
+ if ((uiSectorSize < MIN_SECTOR_SIZE) ||
+ (uiSectorSize > MAX_SECTOR_SIZE)) {
+ if (copy_to_user(IoBuffer.OutputBuffer,
+ &Adapter->uiSectorSize, sizeof(UINT)))
+ return -EFAULT;
+ } else {
+ if (IsFlash2x(Adapter)) {
+ if (copy_to_user(IoBuffer.OutputBuffer,
+ &Adapter->uiSectorSize, sizeof(UINT)))
+ return -EFAULT;
+ } else {
+ if ((TRUE == Adapter->bShutStatus) ||
+ (TRUE == Adapter->IdleMode)) {
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "Device is in Idle/Shutdown Mode\n");
+ return -EACCES;
+ }
+
+ Adapter->uiSectorSize = uiSectorSize;
+ BcmUpdateSectorSize(Adapter,
+ Adapter->uiSectorSize);
+ }
+ }
+ Status = STATUS_SUCCESS;
+ } else {
+ Status = STATUS_FAILURE;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_set_debug(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+#ifdef DEBUG
+ struct bcm_ioctl_buffer IoBuffer;
+ struct bcm_user_debug_state sUserDebugState;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "In SET_DEBUG ioctl\n");
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer,
+ sizeof(struct bcm_user_debug_state)))
+ return -EFAULT;
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
+ sUserDebugState.OnOff, sUserDebugState.Type);
+ /* sUserDebugState.Subtype <<= 1; */
+ sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "actual Subtype=0x%x\n", sUserDebugState.Subtype);
+
+ /* Update new 'DebugState' in the Adapter */
+ Adapter->stDebugState.type |= sUserDebugState.Type;
+ /* Subtype: A bitmap of 32 bits for Subtype per Type.
+ * Valid indexes in 'subtype' array: 1,2,4,8
+ * corresponding to valid Type values. Hence we can use the 'Type' field
+ * as the index value, ignoring the array entries 0,3,5,6,7 !
+ */
+ if (sUserDebugState.OnOff)
+ Adapter->stDebugState.subtype[sUserDebugState.Type] |=
+ sUserDebugState.Subtype;
+ else
+ Adapter->stDebugState.subtype[sUserDebugState.Type] &=
+ ~sUserDebugState.Subtype;
+
+ BCM_SHOW_DEBUG_BITMAP(Adapter);
+#endif
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_nvm_rw(void __user *argp,
+ struct bcm_mini_adapter *Adapter, UINT cmd)
+{
+ struct bcm_nvm_readwrite stNVMReadWrite;
+ struct timeval tv0, tv1;
+ struct bcm_ioctl_buffer IoBuffer;
+ PUCHAR pReadData = NULL;
+ INT Status = STATUS_FAILURE;
+
+ memset(&tv0, 0, sizeof(struct timeval));
+ memset(&tv1, 0, sizeof(struct timeval));
+ if ((Adapter->eNVMType == NVM_FLASH) &&
+ (Adapter->uiFlashLayoutMajorVersion == 0)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
+ return -EFAULT;
+ }
+
+ if (IsFlash2x(Adapter)) {
+ if ((Adapter->eActiveDSD != DSD0) &&
+ (Adapter->eActiveDSD != DSD1) &&
+ (Adapter->eActiveDSD != DSD2)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "No DSD is active..hence NVM Command is blocked");
+ return STATUS_FAILURE;
+ }
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (copy_from_user(&stNVMReadWrite,
+ (IOCTL_BCM_NVM_READ == cmd) ?
+ IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
+ sizeof(struct bcm_nvm_readwrite)))
+ return -EFAULT;
+
+ /*
+ * Deny the access if the offset crosses the cal area limit.
+ */
+ if (stNVMReadWrite.uiNumBytes > Adapter->uiNVMDSDSize)
+ return STATUS_FAILURE;
+
+ if (stNVMReadWrite.uiOffset >
+ Adapter->uiNVMDSDSize - stNVMReadWrite.uiNumBytes)
+ return STATUS_FAILURE;
+
+ pReadData = memdup_user(stNVMReadWrite.pBuffer,
+ stNVMReadWrite.uiNumBytes);
+ if (IS_ERR(pReadData))
+ return PTR_ERR(pReadData);
+
+ do_gettimeofday(&tv0);
+ if (IOCTL_BCM_NVM_READ == cmd) {
+ int ret = bcm_handle_nvm_read_cmd(Adapter, pReadData,
+ &stNVMReadWrite);
+ if (ret != STATUS_SUCCESS)
+ return ret;
+ } else {
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return -EACCES;
+ }
+
+ Adapter->bHeaderChangeAllowed = TRUE;
+ if (IsFlash2x(Adapter)) {
+ int ret = handle_flash2x_adapter(Adapter,
+ pReadData,
+ &stNVMReadWrite);
+ if (ret != STATUS_SUCCESS)
+ return ret;
+ }
+
+ Status = BeceemNVMWrite(Adapter, (PUINT)pReadData,
+ stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes,
+ stNVMReadWrite.bVerify);
+ if (IsFlash2x(Adapter))
+ BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
+
+ Adapter->bHeaderChangeAllowed = false;
+
+ up(&Adapter->NVMRdmWrmLock);
+
+ if (Status != STATUS_SUCCESS) {
+ kfree(pReadData);
+ return Status;
+ }
+ }
+
+ do_gettimeofday(&tv1);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ " timetaken by Write/read :%ld msec\n",
+ (tv1.tv_sec - tv0.tv_sec)*1000 +
+ (tv1.tv_usec - tv0.tv_usec)/1000);
+
+ kfree(pReadData);
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_flash2x_section_read(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_flash2x_readwrite sFlash2xRead = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ PUCHAR pReadBuff = NULL;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT ReadBytes = 0;
+ UINT ReadOffset = 0;
+ INT Status = STATUS_FAILURE;
+ void __user *OutPutBuff;
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ /* Reading FLASH 2.x READ structure */
+ if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,
+ sizeof(struct bcm_flash2x_readwrite)))
+ return -EFAULT;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.Section :%x",
+ sFlash2xRead.Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.offset :%x",
+ sFlash2xRead.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.numOfBytes :%x",
+ sFlash2xRead.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.bVerify :%x\n",
+ sFlash2xRead.bVerify);
+
+ /* This was internal to driver for raw read.
+ * now it has ben exposed to user space app.
+ */
+ if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == false)
+ return STATUS_FAILURE;
+
+ NOB = sFlash2xRead.numOfBytes;
+ if (NOB > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB;
+
+ ReadOffset = sFlash2xRead.offset;
+ OutPutBuff = IoBuffer.OutputBuffer;
+ pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
+
+ if (pReadBuff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Memory allocation failed for Flash 2.x Read Structure");
+ return -ENOMEM;
+ }
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EACCES;
+ }
+
+ while (NOB) {
+ if (NOB > Adapter->uiSectorSize)
+ ReadBytes = Adapter->uiSectorSize;
+ else
+ ReadBytes = NOB;
+
+ /* Reading the data from Flash 2.x */
+ Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff,
+ sFlash2xRead.Section, ReadOffset, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Flash 2x read err with Status :%d",
+ Status);
+ break;
+ }
+
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, pReadBuff, ReadBytes);
+
+ Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Copy to use failed with status :%d", Status);
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EFAULT;
+ }
+ NOB = NOB - ReadBytes;
+ if (NOB) {
+ ReadOffset = ReadOffset + ReadBytes;
+ OutPutBuff = OutPutBuff + ReadBytes;
+ }
+ }
+
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return Status;
+}
+
+static int bcm_char_ioctl_flash2x_section_write(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_flash2x_readwrite sFlash2xWrite = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ PUCHAR pWriteBuff;
+ void __user *InputAddr;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT WriteOffset = 0;
+ UINT WriteBytes = 0;
+ INT Status = STATUS_FAILURE;
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ /* First make this False so that we can enable the Sector
+ * Permission Check in BeceemFlashBulkWrite
+ */
+ Adapter->bAllDSDWriteAllow = false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ /* Reading FLASH 2.x READ structure */
+ if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer,
+ sizeof(struct bcm_flash2x_readwrite)))
+ return -EFAULT;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify);
+
+ if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1)
+ && (sFlash2xWrite.Section != VSA2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Only VSA write is allowed");
+ return -EINVAL;
+ }
+
+ if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == false)
+ return STATUS_FAILURE;
+
+ InputAddr = sFlash2xWrite.pDataBuff;
+ WriteOffset = sFlash2xWrite.offset;
+ NOB = sFlash2xWrite.numOfBytes;
+
+ if (NOB > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB;
+
+ pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
+
+ if (pWriteBuff == NULL)
+ return -ENOMEM;
+
+ /* extracting the remainder of the given offset. */
+ WriteBytes = Adapter->uiSectorSize;
+ if (WriteOffset % Adapter->uiSectorSize) {
+ WriteBytes = Adapter->uiSectorSize -
+ (WriteOffset % Adapter->uiSectorSize);
+ }
+
+ if (NOB < WriteBytes)
+ WriteBytes = NOB;
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ return -EACCES;
+ }
+
+ BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section);
+ do {
+ Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy to user failed with status :%d", Status);
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ return -EFAULT;
+ }
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS,
+ OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
+
+ /* Writing the data from Flash 2.x */
+ Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff,
+ sFlash2xWrite.Section,
+ WriteOffset,
+ WriteBytes,
+ sFlash2xWrite.bVerify);
+
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash 2x read err with Status :%d", Status);
+ break;
+ }
+
+ NOB = NOB - WriteBytes;
+ if (NOB) {
+ WriteOffset = WriteOffset + WriteBytes;
+ InputAddr = InputAddr + WriteBytes;
+ if (NOB > Adapter->uiSectorSize)
+ WriteBytes = Adapter->uiSectorSize;
+ else
+ WriteBytes = NOB;
+ }
+ } while (NOB > 0);
+
+ BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section);
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ return Status;
+}
+
+static int bcm_char_ioctl_flash2x_section_bitmap(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_flash2x_bitmap *psFlash2xBitMap;
+ struct bcm_ioctl_buffer IoBuffer;
+
+BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength != sizeof(struct bcm_flash2x_bitmap))
+ return -EINVAL;
+
+ psFlash2xBitMap = kzalloc(sizeof(struct bcm_flash2x_bitmap),
+ GFP_KERNEL);
+
+ if (psFlash2xBitMap == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Memory is not available");
+ return -ENOMEM;
+ }
+
+ /* Reading the Flash Sectio Bit map */
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(psFlash2xBitMap);
+ return -EACCES;
+ }
+
+ BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
+ up(&Adapter->NVMRdmWrmLock);
+ if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap,
+ sizeof(struct bcm_flash2x_bitmap))) {
+ kfree(psFlash2xBitMap);
+ return -EFAULT;
+ }
+
+ kfree(psFlash2xBitMap);
+ return STATUS_FAILURE;
+}
+
+static int bcm_char_ioctl_set_active_section(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ enum bcm_flash2x_section_val eFlash2xSectionVal = 0;
+ INT Status = STATUS_FAILURE;
+ struct bcm_ioctl_buffer IoBuffer;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_SET_ACTIVE_SECTION Called");
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ Status = copy_from_user(&IoBuffer, argp,
+ sizeof(struct bcm_ioctl_buffer));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+
+ Status = copy_from_user(&eFlash2xSectionVal,
+ IoBuffer.InputBuffer, sizeof(INT));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of flash section val failed");
+ return -EFAULT;
+ }
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal);
+ if (Status)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed to make it's priority Highest. Status %d",
+ Status);
+
+ up(&Adapter->NVMRdmWrmLock);
+
+ return Status;
+}
+
+static int bcm_char_ioctl_copy_section(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_flash2x_copy_section sCopySectStrut = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+ INT Status = STATUS_SUCCESS;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_COPY_SECTION Called");
+
+ Adapter->bAllDSDWriteAllow = false;
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ Status = copy_from_user(&IoBuffer, argp,
+ sizeof(struct bcm_ioctl_buffer));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of IOCTL BUFFER failed Status :%d",
+ Status);
+ return -EFAULT;
+ }
+
+ Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer,
+ sizeof(struct bcm_flash2x_copy_section));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of Copy_Section_Struct failed with Status :%d",
+ Status);
+ return -EFAULT;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Source SEction :%x", sCopySectStrut.SrcSection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Destination SEction :%x", sCopySectStrut.DstSection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "offset :%x", sCopySectStrut.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "NOB :%x", sCopySectStrut.numOfBytes);
+
+ if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Source Section<%x> does not exist in Flash ",
+ sCopySectStrut.SrcSection);
+ return -EINVAL;
+ }
+
+ if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Destinatio Section<%x> does not exist in Flash ",
+ sCopySectStrut.DstSection);
+ return -EINVAL;
+ }
+
+ if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Source and Destination section should be different");
+ return -EINVAL;
+ }
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ if (sCopySectStrut.SrcSection == ISO_IMAGE1 ||
+ sCopySectStrut.SrcSection == ISO_IMAGE2) {
+ if (IsNonCDLessDevice(Adapter)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Device is Non-CDLess hence won't have ISO !!");
+ Status = -EINVAL;
+ } else if (sCopySectStrut.numOfBytes == 0) {
+ Status = BcmCopyISO(Adapter, sCopySectStrut);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Partial Copy of ISO section is not Allowed..");
+ Status = STATUS_FAILURE;
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+ }
+
+ Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
+ sCopySectStrut.DstSection,
+ sCopySectStrut.offset,
+ sCopySectStrut.numOfBytes);
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+}
+
+static int bcm_char_ioctl_get_flash_cs_info(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ INT Status = STATUS_SUCCESS;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ " IOCTL_BCM_GET_FLASH_CS_INFO Called");
+
+ Status = copy_from_user(&IoBuffer, argp,
+ sizeof(struct bcm_ioctl_buffer));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+
+ if (Adapter->eNVMType != NVM_FLASH) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Connected device does not have flash");
+ return -EINVAL;
+ }
+
+ if (IsFlash2x(Adapter) == TRUE) {
+ if (IoBuffer.OutputLength < sizeof(struct bcm_flash2x_cs_info))
+ return -EINVAL;
+
+ if (copy_to_user(IoBuffer.OutputBuffer,
+ Adapter->psFlash2xCSInfo,
+ sizeof(struct bcm_flash2x_cs_info)))
+ return -EFAULT;
+ } else {
+ if (IoBuffer.OutputLength < sizeof(struct bcm_flash_cs_info))
+ return -EINVAL;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo,
+ sizeof(struct bcm_flash_cs_info)))
+ return -EFAULT;
+ }
+ return Status;
+}
+
+static int bcm_char_ioctl_select_dsd(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ INT Status = STATUS_FAILURE;
+ UINT SectOfset = 0;
+ enum bcm_flash2x_section_val eFlash2xSectionVal;
+
+ eFlash2xSectionVal = NO_SECTION_VAL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_SELECT_DSD Called");
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+
+ Status = copy_from_user(&IoBuffer, argp,
+ sizeof(struct bcm_ioctl_buffer));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of IOCTL BUFFER failed");
+ return -EFAULT;
+ }
+ Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer,
+ sizeof(INT));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy of flash section val failed");
+ return -EFAULT;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Read Section :%d", eFlash2xSectionVal);
+ if ((eFlash2xSectionVal != DSD0) &&
+ (eFlash2xSectionVal != DSD1) &&
+ (eFlash2xSectionVal != DSD2)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Passed section<%x> is not DSD section",
+ eFlash2xSectionVal);
+ return STATUS_FAILURE;
+ }
+
+ SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
+ if (SectOfset == INVALID_OFFSET) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Provided Section val <%d> does not exist in Flash 2.x",
+ eFlash2xSectionVal);
+ return -EINVAL;
+ }
+
+ Adapter->bAllDSDWriteAllow = TRUE;
+ Adapter->ulFlashCalStart = SectOfset;
+ Adapter->eActiveDSD = eFlash2xSectionVal;
+
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_nvm_raw_read(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_nvm_readwrite stNVMRead;
+ struct bcm_ioctl_buffer IoBuffer;
+ unsigned int NOB;
+ INT BuffSize;
+ INT ReadOffset = 0;
+ UINT ReadBytes = 0;
+ PUCHAR pReadBuff;
+ void __user *OutPutBuff;
+ INT Status = STATUS_FAILURE;
+
+ if (Adapter->eNVMType != NVM_FLASH) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "NVM TYPE is not Flash");
+ return -EINVAL;
+ }
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "copy_from_user 1 failed\n");
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,
+ sizeof(struct bcm_nvm_readwrite)))
+ return -EFAULT;
+
+ NOB = stNVMRead.uiNumBytes;
+ /* In Raw-Read max Buff size : 64MB */
+
+ if (NOB > DEFAULT_BUFF_SIZE)
+ BuffSize = DEFAULT_BUFF_SIZE;
+ else
+ BuffSize = NOB;
+
+ ReadOffset = stNVMRead.uiOffset;
+ OutPutBuff = stNVMRead.pBuffer;
+
+ pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
+ if (pReadBuff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Memory allocation failed for Flash 2.x Read Structure");
+ return -ENOMEM;
+ }
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Device is in Idle/Shutdown Mode\n");
+ kfree(pReadBuff);
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ Adapter->bFlashRawRead = TRUE;
+
+ while (NOB) {
+ if (NOB > DEFAULT_BUFF_SIZE)
+ ReadBytes = DEFAULT_BUFF_SIZE;
+ else
+ ReadBytes = NOB;
+
+ /* Reading the data from Flash 2.x */
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff,
+ ReadOffset, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Flash 2x read err with Status :%d",
+ Status);
+ break;
+ }
+
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, pReadBuff, ReadBytes);
+
+ Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Copy to use failed with status :%d",
+ Status);
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EFAULT;
+ }
+ NOB = NOB - ReadBytes;
+ if (NOB) {
+ ReadOffset = ReadOffset + ReadBytes;
+ OutPutBuff = OutPutBuff + ReadBytes;
+ }
+ }
+ Adapter->bFlashRawRead = false;
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return Status;
+}
+
+static int bcm_char_ioctl_cntrlmsg_mask(void __user *argp,
+ struct bcm_mini_adapter *Adapter, struct bcm_tarang_data *pTarang)
+{
+ struct bcm_ioctl_buffer IoBuffer;
+ INT Status = STATUS_FAILURE;
+ ULONG RxCntrlMsgBitMask = 0;
+
+ /* Copy Ioctl Buffer structure */
+ Status = copy_from_user(&IoBuffer, argp,
+ sizeof(struct bcm_ioctl_buffer));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "copy of Ioctl buffer is failed from user space");
+ return -EFAULT;
+ }
+
+ if (IoBuffer.InputLength != sizeof(unsigned long))
+ return -EINVAL;
+
+ Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer,
+ IoBuffer.InputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "copy of control bit mask failed from user space");
+ return -EFAULT;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "\n Got user defined cntrl msg bit mask :%lx",
+ RxCntrlMsgBitMask);
+ pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
+
+ return Status;
+}
+
+static int bcm_char_ioctl_get_device_driver_info(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_driver_info DevInfo;
+ struct bcm_ioctl_buffer IoBuffer;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
+ memset(&DevInfo, 0, sizeof(DevInfo));
+ DevInfo.MaxRDMBufferSize = BUFFER_4K;
+ DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+ DevInfo.u32RxAlignmentCorrection = 0;
+ DevInfo.u32NVMType = Adapter->eNVMType;
+ DevInfo.u32InterfaceType = BCM_USB;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(DevInfo))
+ return -EINVAL;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
+ return -EFAULT;
+
+ return STATUS_SUCCESS;
+}
+
+static int bcm_char_ioctl_time_since_net_entry(void __user *argp,
+ struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_time_elapsed stTimeElapsedSinceNetEntry = {0};
+ struct bcm_ioctl_buffer IoBuffer;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(struct bcm_time_elapsed))
+ return -EINVAL;
+
+ stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry =
+ get_seconds() - Adapter->liTimeSinceLastNetEntry;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry,
+ sizeof(struct bcm_time_elapsed)))
+ return -EFAULT;
+
+ return STATUS_SUCCESS;
+}
+
+
+static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
+{
+ struct bcm_tarang_data *pTarang = filp->private_data;
+ void __user *argp = (void __user *)arg;
+ struct bcm_mini_adapter *Adapter = pTarang->Adapter;
+ INT Status = STATUS_FAILURE;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX",
+ cmd, arg);
+
+ if (_IOC_TYPE(cmd) != BCM_IOCTL)
+ return -EFAULT;
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
+ else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
+ Status = STATUS_SUCCESS;
+
+ if (Status)
+ return -EFAULT;
+
+ if (Adapter->device_removed)
+ return -EFAULT;
+
+ if (false == Adapter->fw_download_done) {
+ switch (cmd) {
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ:
+ case IOCTL_BCM_GPIO_SET_REQUEST:
+ case IOCTL_BCM_GPIO_STATUS_REQUEST:
+ return -EACCES;
+ default:
+ break;
+ }
+ }
+
+ Status = vendorextnIoctl(Adapter, cmd, arg);
+ if (Status != CONTINUE_COMMON_PATH)
+ return Status;
+
+ switch (cmd) {
+ /* Rdms for Swin Idle... */
+ case IOCTL_BCM_REGISTER_READ_PRIVATE:
+ Status = bcm_char_ioctl_reg_read_private(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
+ Status = bcm_char_ioctl_reg_write_private(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_REGISTER_READ:
+ case IOCTL_BCM_EEPROM_REGISTER_READ:
+ Status = bcm_char_ioctl_eeprom_reg_read(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_REGISTER_WRITE:
+ case IOCTL_BCM_EEPROM_REGISTER_WRITE:
+ Status = bcm_char_ioctl_eeprom_reg_write(argp, Adapter, cmd);
+ return Status;
+
+ case IOCTL_BCM_GPIO_SET_REQUEST:
+ Status = bcm_char_ioctl_gpio_set_request(argp, Adapter);
+ return Status;
+
+ case BCM_LED_THREAD_STATE_CHANGE_REQ:
+ Status = bcm_char_ioctl_led_thread_state_change_req(argp,
+ Adapter);
+ return Status;
+
+ case IOCTL_BCM_GPIO_STATUS_REQUEST:
+ Status = bcm_char_ioctl_gpio_status_request(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GPIO_MULTI_REQUEST:
+ Status = bcm_char_ioctl_gpio_multi_request(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GPIO_MODE_REQUEST:
+ Status = bcm_char_ioctl_gpio_mode_request(argp, Adapter);
+ return Status;
+
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ:
+ Status = bcm_char_ioctl_misc_request(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD_START:
+ Status = bcm_char_ioctl_buffer_download_start(Adapter);
+ return Status;
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD:
+ Status = bcm_char_ioctl_buffer_download(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
+ Status = bcm_char_ioctl_buffer_download_stop(argp, Adapter);
+ return Status;
+
+
+ case IOCTL_BE_BUCKET_SIZE:
+ Status = 0;
+ if (get_user(Adapter->BEBucketSize,
+ (unsigned long __user *)arg))
+ Status = -EFAULT;
+ break;
+
+ case IOCTL_RTPS_BUCKET_SIZE:
+ Status = 0;
+ if (get_user(Adapter->rtPSBucketSize,
+ (unsigned long __user *)arg))
+ Status = -EFAULT;
+ break;
+
+ case IOCTL_CHIP_RESET:
+ Status = bcm_char_ioctl_chip_reset(Adapter);
+ return Status;
+
+ case IOCTL_QOS_THRESHOLD:
+ Status = bcm_char_ioctl_qos_threshold(arg, Adapter);
+ return Status;
+
+ case IOCTL_DUMP_PACKET_INFO:
+ DumpPackInfo(Adapter);
+ DumpPhsRules(&Adapter->stBCMPhsContext);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_GET_PACK_INFO:
+ if (copy_to_user(argp, &Adapter->PackInfo,
+ sizeof(struct bcm_packet_info)*NO_OF_QUEUES))
+ return -EFAULT;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_SWITCH_TRANSFER_MODE:
+ Status = bcm_char_ioctl_switch_transfer_mode(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GET_DRIVER_VERSION:
+ Status = bcm_char_ioctl_get_driver_version(argp);
+ return Status;
+
+ case IOCTL_BCM_GET_CURRENT_STATUS:
+ Status = bcm_char_ioctl_get_current_status(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_SET_MAC_TRACING:
+ Status = bcm_char_ioctl_set_mac_tracing(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GET_DSX_INDICATION:
+ Status = bcm_char_ioctl_get_dsx_indication(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GET_HOST_MIBS:
+ Status = bcm_char_ioctl_get_host_mibs(argp, Adapter, pTarang);
+ return Status;
+
+ case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
+ if ((false == Adapter->bTriedToWakeUpFromlowPowerMode) &&
+ (TRUE == Adapter->IdleMode)) {
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ }
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_BULK_WRM:
+ Status = bcm_char_ioctl_bulk_wrm(argp, Adapter, cmd);
+ return Status;
+
+ case IOCTL_BCM_GET_NVM_SIZE:
+ Status = bcm_char_ioctl_get_nvm_size(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_CAL_INIT:
+ Status = bcm_char_ioctl_cal_init(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_SET_DEBUG:
+ Status = bcm_char_ioctl_set_debug(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_NVM_READ:
+ case IOCTL_BCM_NVM_WRITE:
+ Status = bcm_char_ioctl_nvm_rw(argp, Adapter, cmd);
+ return Status;
+
+ case IOCTL_BCM_FLASH2X_SECTION_READ:
+ Status = bcm_char_ioctl_flash2x_section_read(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_FLASH2X_SECTION_WRITE:
+ Status = bcm_char_ioctl_flash2x_section_write(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP:
+ Status = bcm_char_ioctl_flash2x_section_bitmap(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_SET_ACTIVE_SECTION:
+ Status = bcm_char_ioctl_set_active_section(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION:
+ /* Right Now we are taking care of only DSD */
+ Adapter->bAllDSDWriteAllow = false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_COPY_SECTION:
+ Status = bcm_char_ioctl_copy_section(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_GET_FLASH_CS_INFO:
+ Status = bcm_char_ioctl_get_flash_cs_info(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_SELECT_DSD:
+ Status = bcm_char_ioctl_select_dsd(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_NVM_RAW_READ:
+ Status = bcm_char_ioctl_nvm_raw_read(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_CNTRLMSG_MASK:
+ Status = bcm_char_ioctl_cntrlmsg_mask(argp, Adapter, pTarang);
+ return Status;
+
+ case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
+ Status = bcm_char_ioctl_get_device_driver_info(argp, Adapter);
+ return Status;
+
+ case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
+ Status = bcm_char_ioctl_time_since_net_entry(argp, Adapter);
+ return Status;
+
+ case IOCTL_CLOSE_NOTIFICATION:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_CLOSE_NOTIFICATION");
+ break;
+
+ default:
+ pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
+ Status = STATUS_FAILURE;
+ break;
+ }
+ return Status;
+}
+
+
+static const struct file_operations bcm_fops = {
+ .owner = THIS_MODULE,
+ .open = bcm_char_open,
+ .release = bcm_char_release,
+ .read = bcm_char_read,
+ .unlocked_ioctl = bcm_char_ioctl,
+ .llseek = no_llseek,
+};
+
+int register_control_device_interface(struct bcm_mini_adapter *Adapter)
+{
+
+ if (Adapter->major > 0)
+ return Adapter->major;
+
+ Adapter->major = register_chrdev(0, DEV_NAME, &bcm_fops);
+ if (Adapter->major < 0) {
+ pr_err(DRV_NAME ": could not created character device\n");
+ return Adapter->major;
+ }
+
+ Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL,
+ MKDEV(Adapter->major, 0),
+ Adapter, DEV_NAME);
+
+ if (IS_ERR(Adapter->pstCreatedClassDevice)) {
+ pr_err(DRV_NAME ": class device create failed\n");
+ unregister_chrdev(Adapter->major, DEV_NAME);
+ return PTR_ERR(Adapter->pstCreatedClassDevice);
+ }
+
+ return 0;
+}
+
+void unregister_control_device_interface(struct bcm_mini_adapter *Adapter)
+{
+ if (Adapter->major > 0) {
+ device_destroy(bcm_class, MKDEV(Adapter->major, 0));
+ unregister_chrdev(Adapter->major, DEV_NAME);
+ }
+}
+
diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c
new file mode 100644
index 00000000000..95a2358267b
--- /dev/null
+++ b/drivers/staging/bcm/Bcmnet.c
@@ -0,0 +1,241 @@
+#include "headers.h"
+
+struct net_device *gblpnetdev;
+
+static INT bcm_open(struct net_device *dev)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+
+ if (Adapter->fw_download_done == false) {
+ pr_notice(PFX "%s: link up failed (download in progress)\n",
+ dev->name);
+ return -EBUSY;
+ }
+
+ if (netif_msg_ifup(Adapter))
+ pr_info(PFX "%s: enabling interface\n", dev->name);
+
+ if (Adapter->LinkUpStatus) {
+ if (netif_msg_link(Adapter))
+ pr_info(PFX "%s: link up\n", dev->name);
+
+ netif_carrier_on(Adapter->dev);
+ netif_start_queue(Adapter->dev);
+ }
+
+ return 0;
+}
+
+static INT bcm_close(struct net_device *dev)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+
+ if (netif_msg_ifdown(Adapter))
+ pr_info(PFX "%s: disabling interface\n", dev->name);
+
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ return ClassifyPacket(netdev_priv(dev), skb);
+}
+
+/*******************************************************************
+* Function - bcm_transmit()
+*
+* Description - This is the main transmit function for our virtual
+* interface(eth0). It handles the ARP packets. It
+* clones this packet and then Queue it to a suitable
+* Queue. Then calls the transmit_packet().
+*
+* Parameter - skb - Pointer to the socket buffer structure
+* dev - Pointer to the virtual net device structure
+*
+*********************************************************************/
+
+static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+ u16 qindex = skb_get_queue_mapping(skb);
+
+
+ if (Adapter->device_removed || !Adapter->LinkUpStatus)
+ goto drop;
+
+ if (Adapter->TransferMode != IP_PACKET_ONLY_MODE)
+ goto drop;
+
+ if (INVALID_QUEUE_INDEX == qindex)
+ goto drop;
+
+ if (Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >=
+ SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
+ return NETDEV_TX_BUSY;
+
+ /* Now Enqueue the packet */
+ if (netif_msg_tx_queued(Adapter))
+ pr_info(PFX "%s: enqueueing packet to queue %d\n",
+ dev->name, qindex);
+
+ spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
+ Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
+ Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;
+
+ *((B_UINT32 *) skb->cb + SKB_CB_LATENCY_OFFSET) = jiffies;
+ ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
+ Adapter->PackInfo[qindex].LastTxQueue, skb);
+ atomic_inc(&Adapter->TotalPacketCount);
+ spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);
+
+ /* FIXME - this is racy and incorrect, replace with work queue */
+ if (!atomic_read(&Adapter->TxPktAvail)) {
+ atomic_set(&Adapter->TxPktAvail, 1);
+ wake_up(&Adapter->tx_packet_wait_queue);
+ }
+ return NETDEV_TX_OK;
+
+ drop:
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+
+
+/**
+@ingroup init_functions
+Register other driver entry points with the kernel
+*/
+static const struct net_device_ops bcmNetDevOps = {
+ .ndo_open = bcm_open,
+ .ndo_stop = bcm_close,
+ .ndo_start_xmit = bcm_transmit,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_select_queue = bcm_select_queue,
+};
+
+static struct device_type wimax_type = {
+ .name = "wimax",
+};
+
+static int bcm_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ cmd->supported = 0;
+ cmd->advertising = 0;
+ cmd->speed = SPEED_10000;
+ cmd->duplex = DUPLEX_FULL;
+ cmd->port = PORT_TP;
+ cmd->phy_address = 0;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
+ return 0;
+}
+
+static void bcm_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+ struct bcm_interface_adapter *psIntfAdapter =
+ Adapter->pvInterfaceAdapter;
+ struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface);
+
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u",
+ Adapter->uiFlashLayoutMajorVersion,
+ Adapter->uiFlashLayoutMinorVersion);
+
+ usb_make_path(udev, info->bus_info, sizeof(info->bus_info));
+}
+
+static u32 bcm_get_link(struct net_device *dev)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+
+ return Adapter->LinkUpStatus;
+}
+
+static u32 bcm_get_msglevel(struct net_device *dev)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+
+ return Adapter->msg_enable;
+}
+
+static void bcm_set_msglevel(struct net_device *dev, u32 level)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
+
+ Adapter->msg_enable = level;
+}
+
+static const struct ethtool_ops bcm_ethtool_ops = {
+ .get_settings = bcm_get_settings,
+ .get_drvinfo = bcm_get_drvinfo,
+ .get_link = bcm_get_link,
+ .get_msglevel = bcm_get_msglevel,
+ .set_msglevel = bcm_set_msglevel,
+};
+
+int register_networkdev(struct bcm_mini_adapter *Adapter)
+{
+ struct net_device *net = Adapter->dev;
+ struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter;
+ struct usb_interface *udev = IntfAdapter->interface;
+ struct usb_device *xdev = IntfAdapter->udev;
+
+ int result;
+
+ net->netdev_ops = &bcmNetDevOps;
+ net->ethtool_ops = &bcm_ethtool_ops;
+ net->mtu = MTU_SIZE; /* 1400 Bytes */
+ net->tx_queue_len = TX_QLEN;
+ net->flags |= IFF_NOARP;
+
+ netif_carrier_off(net);
+
+ SET_NETDEV_DEVTYPE(net, &wimax_type);
+
+ /* Read the MAC Address from EEPROM */
+ result = ReadMacAddressFromNVM(Adapter);
+ if (result != STATUS_SUCCESS) {
+ dev_err(&udev->dev,
+ PFX "Error in Reading the mac Address: %d", result);
+ return -EIO;
+ }
+
+ result = register_netdev(net);
+ if (result)
+ return result;
+
+ gblpnetdev = Adapter->dev;
+
+ if (netif_msg_probe(Adapter))
+ dev_info(&udev->dev, PFX "%s: register usb-%s-%s %pM\n",
+ net->name, xdev->bus->bus_name, xdev->devpath,
+ net->dev_addr);
+
+ return 0;
+}
+
+void unregister_networkdev(struct bcm_mini_adapter *Adapter)
+{
+ struct net_device *net = Adapter->dev;
+ struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter;
+ struct usb_interface *udev = IntfAdapter->interface;
+ struct usb_device *xdev = IntfAdapter->udev;
+
+ if (netif_msg_probe(Adapter))
+ dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n",
+ net->name, xdev->bus->bus_name, xdev->devpath);
+
+ unregister_netdev(Adapter->dev);
+}
diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c
new file mode 100644
index 00000000000..fb1d932c5d7
--- /dev/null
+++ b/drivers/staging/bcm/CmHost.c
@@ -0,0 +1,2253 @@
+/************************************************************
+ * CMHOST.C
+ * This file contains the routines for handling Connection
+ * Management.
+ ************************************************************/
+
+#include "headers.h"
+
+enum E_CLASSIFIER_ACTION {
+ eInvalidClassifierAction,
+ eAddClassifier,
+ eReplaceClassifier,
+ eDeleteClassifier
+};
+
+static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter,
+ B_UINT16 tid);
+static void restore_endianess_of_pstClassifierEntry(
+ struct bcm_classifier_rule *pstClassifierEntry,
+ enum bcm_ipaddr_context eIpAddrContext);
+
+static void apply_phs_rule_to_all_classifiers(
+ register struct bcm_mini_adapter *Adapter,
+ register UINT uiSearchRuleIndex,
+ USHORT uVCID,
+ struct bcm_phs_rule *sPhsRule,
+ struct bcm_phs_rules *cPhsRule,
+ struct bcm_add_indication_alt *pstAddIndication);
+
+/************************************************************
+ * Function - SearchSfid
+ *
+ * Description - This routinue would search QOS queues having
+ * specified SFID as input parameter.
+ *
+ * Parameters - Adapter: Pointer to the Adapter structure
+ * uiSfid : Given SFID for matching
+ *
+ * Returns - Queue index for this SFID(If matched)
+ * Else Invalid Queue Index(If Not matched)
+ ************************************************************/
+int SearchSfid(struct bcm_mini_adapter *Adapter, UINT uiSfid)
+{
+ int i;
+
+ for (i = (NO_OF_QUEUES-1); i >= 0; i--)
+ if (Adapter->PackInfo[i].ulSFID == uiSfid)
+ return i;
+
+ return NO_OF_QUEUES+1;
+}
+
+/***************************************************************
+ * Function -SearchFreeSfid
+ *
+ * Description - This routinue would search Free available SFID.
+ *
+ * Parameter - Adapter: Pointer to the Adapter structure
+ *
+ * Returns - Queue index for the free SFID
+ * Else returns Invalid Index.
+ ****************************************************************/
+static int SearchFreeSfid(struct bcm_mini_adapter *Adapter)
+{
+ int i;
+
+ for (i = 0; i < (NO_OF_QUEUES-1); i++)
+ if (Adapter->PackInfo[i].ulSFID == 0)
+ return i;
+
+ return NO_OF_QUEUES+1;
+}
+
+/*
+ * Function: SearchClsid
+ * Description: This routinue would search Classifier having specified ClassifierID as input parameter
+ * Input parameters: struct bcm_mini_adapter *Adapter - Adapter Context
+ * unsigned int uiSfid - The SF in which the classifier is to searched
+ * B_UINT16 uiClassifierID - The classifier ID to be searched
+ * Return: int :Classifier table index of matching entry
+ */
+static int SearchClsid(struct bcm_mini_adapter *Adapter,
+ ULONG ulSFID,
+ B_UINT16 uiClassifierID)
+{
+ int i;
+
+ for (i = 0; i < MAX_CLASSIFIERS; i++) {
+ if ((Adapter->astClassifierTable[i].bUsed) &&
+ (Adapter->astClassifierTable[i].uiClassifierRuleIndex
+ == uiClassifierID) &&
+ (Adapter->astClassifierTable[i].ulSFID == ulSFID))
+ return i;
+ }
+
+ return MAX_CLASSIFIERS+1;
+}
+
+/*
+ * @ingroup ctrl_pkt_functions
+ * This routinue would search Free available Classifier entry in classifier table.
+ * @return free Classifier Entry index in classifier table for specified SF
+ */
+static int SearchFreeClsid(struct bcm_mini_adapter *Adapter /**Adapter Context*/)
+{
+ int i;
+
+ for (i = 0; i < MAX_CLASSIFIERS; i++) {
+ if (!Adapter->astClassifierTable[i].bUsed)
+ return i;
+ }
+
+ return MAX_CLASSIFIERS+1;
+}
+
+static VOID deleteSFBySfid(struct bcm_mini_adapter *Adapter,
+ UINT uiSearchRuleIndex)
+{
+ /* deleting all the packet held in the SF */
+ flush_queue(Adapter, uiSearchRuleIndex);
+
+ /* Deleting the all classifiers for this SF */
+ DeleteAllClassifiersForSF(Adapter, uiSearchRuleIndex);
+
+ /* Resetting only MIBS related entries in the SF */
+ memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0,
+ sizeof(struct bcm_mibs_table));
+}
+
+static inline VOID
+CopyIpAddrToClassifier(struct bcm_classifier_rule *pstClassifierEntry,
+ B_UINT8 u8IpAddressLen, B_UINT8 *pu8IpAddressMaskSrc,
+ bool bIpVersion6, enum bcm_ipaddr_context eIpAddrContext)
+{
+ int i = 0;
+ UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS;
+ UCHAR *ptrClassifierIpAddress = NULL;
+ UCHAR *ptrClassifierIpMask = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ if (bIpVersion6)
+ nSizeOfIPAddressInBytes = IPV6_ADDRESS_SIZEINBYTES;
+
+ /* Destination Ip Address */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Ip Address Range Length:0x%X ", u8IpAddressLen);
+ if ((bIpVersion6 ? (IPV6_ADDRESS_SIZEINBYTES * MAX_IP_RANGE_LENGTH * 2) :
+ (TOTAL_MASKED_ADDRESS_IN_BYTES)) >= u8IpAddressLen) {
+
+ union u_ip_address *st_dest_ip =
+ &pstClassifierEntry->stDestIpAddress;
+
+ union u_ip_address *st_src_ip =
+ &pstClassifierEntry->stSrcIpAddress;
+
+ /*
+ * checking both the mask and address togethor in Classification.
+ * So length will be : TotalLengthInBytes/nSizeOfIPAddressInBytes * 2
+ * (nSizeOfIPAddressInBytes for address and nSizeOfIPAddressInBytes for mask)
+ */
+ if (eIpAddrContext == eDestIpAddress) {
+ pstClassifierEntry->ucIPDestinationAddressLength =
+ u8IpAddressLen/(nSizeOfIPAddressInBytes * 2);
+ if (bIpVersion6) {
+ ptrClassifierIpAddress =
+ st_dest_ip->ucIpv6Address;
+ ptrClassifierIpMask =
+ st_dest_ip->ucIpv6Mask;
+ } else {
+ ptrClassifierIpAddress =
+ st_dest_ip->ucIpv4Address;
+ ptrClassifierIpMask =
+ st_dest_ip->ucIpv4Mask;
+ }
+ } else if (eIpAddrContext == eSrcIpAddress) {
+ pstClassifierEntry->ucIPSourceAddressLength =
+ u8IpAddressLen/(nSizeOfIPAddressInBytes * 2);
+ if (bIpVersion6) {
+ ptrClassifierIpAddress =
+ st_src_ip->ucIpv6Address;
+ ptrClassifierIpMask = st_src_ip->ucIpv6Mask;
+ } else {
+ ptrClassifierIpAddress =
+ st_src_ip->ucIpv4Address;
+ ptrClassifierIpMask = st_src_ip->ucIpv4Mask;
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Address Length:0x%X\n",
+ pstClassifierEntry->ucIPDestinationAddressLength);
+ while ((u8IpAddressLen >= nSizeOfIPAddressInBytes)
+ && (i < MAX_IP_RANGE_LENGTH)) {
+ memcpy(ptrClassifierIpAddress +
+ (i * nSizeOfIPAddressInBytes),
+ (pu8IpAddressMaskSrc
+ + (i * nSizeOfIPAddressInBytes * 2)),
+ nSizeOfIPAddressInBytes);
+
+ if (!bIpVersion6) {
+ if (eIpAddrContext == eSrcIpAddress) {
+ st_src_ip->ulIpv4Addr[i] =
+ ntohl(st_src_ip->ulIpv4Addr[i]);
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ CONN_MSG,
+ DBG_LVL_ALL,
+ "Src Ip Address:0x%luX ",
+ st_src_ip->ulIpv4Addr[i]);
+ } else if (eIpAddrContext == eDestIpAddress) {
+ st_dest_ip->ulIpv4Addr[i] =
+ ntohl(st_dest_ip->ulIpv4Addr[i]);
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ CONN_MSG,
+ DBG_LVL_ALL,
+ "Dest Ip Address:0x%luX ",
+ st_dest_ip->ulIpv4Addr[i]);
+ }
+ }
+ u8IpAddressLen -= nSizeOfIPAddressInBytes;
+ if (u8IpAddressLen >= nSizeOfIPAddressInBytes) {
+ memcpy(ptrClassifierIpMask +
+ (i * nSizeOfIPAddressInBytes),
+ (pu8IpAddressMaskSrc
+ + nSizeOfIPAddressInBytes
+ + (i * nSizeOfIPAddressInBytes * 2)),
+ nSizeOfIPAddressInBytes);
+
+ if (!bIpVersion6) {
+ if (eIpAddrContext == eSrcIpAddress) {
+ st_src_ip->ulIpv4Mask[i] =
+ ntohl(st_src_ip->ulIpv4Mask[i]);
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ CONN_MSG,
+ DBG_LVL_ALL,
+ "Src Ip Mask Address:0x%luX ",
+ st_src_ip->ulIpv4Mask[i]);
+ } else if (eIpAddrContext == eDestIpAddress) {
+ st_dest_ip->ulIpv4Mask[i] =
+ ntohl(st_dest_ip->ulIpv4Mask[i]);
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ CONN_MSG,
+ DBG_LVL_ALL,
+ "Dest Ip Mask Address:0x%luX ",
+ st_dest_ip->ulIpv4Mask[i]);
+ }
+ }
+ u8IpAddressLen -= nSizeOfIPAddressInBytes;
+ }
+ if (u8IpAddressLen == 0)
+ pstClassifierEntry->bDestIpValid = TRUE;
+
+ i++;
+ }
+ if (bIpVersion6) {
+ /* Restore EndianNess of Struct */
+ restore_endianess_of_pstClassifierEntry(
+ pstClassifierEntry,
+ eIpAddrContext
+ );
+ }
+ }
+}
+
+void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter, B_UINT16 TID, bool bFreeAll)
+{
+ int i;
+ struct bcm_targetdsx_buffer *curr_buf;
+
+ for (i = 0; i < Adapter->ulTotalTargetBuffersAvailable; i++) {
+ curr_buf = &Adapter->astTargetDsxBuffer[i];
+
+ if (curr_buf->valid)
+ continue;
+
+ if ((bFreeAll) || (curr_buf->tid == TID)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "ClearTargetDSXBuffer: found tid %d buffer cleared %lx\n",
+ TID, curr_buf->ulTargetDsxBuffer);
+ curr_buf->valid = 1;
+ curr_buf->tid = 0;
+ Adapter->ulFreeTargetBufferCnt++;
+ }
+ }
+}
+
+/*
+ * @ingroup ctrl_pkt_functions
+ * copy classifier rule into the specified SF index
+ */
+static inline VOID CopyClassifierRuleToSF(struct bcm_mini_adapter *Adapter,
+ struct bcm_convergence_types *psfCSType,
+ UINT uiSearchRuleIndex,
+ UINT nClassifierIndex)
+{
+ struct bcm_classifier_rule *pstClassifierEntry = NULL;
+ /* VOID *pvPhsContext = NULL; */
+ int i;
+ /* UCHAR ucProtocolLength=0; */
+ /* ULONG ulPhsStatus; */
+
+ struct bcm_packet_class_rules *pack_class_rule =
+ &psfCSType->cCPacketClassificationRule;
+
+ if (Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value == 0 ||
+ nClassifierIndex > (MAX_CLASSIFIERS-1))
+ return;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Storing Classifier Rule Index : %X",
+ ntohs(pack_class_rule->u16PacketClassificationRuleIndex));
+
+ if (nClassifierIndex > MAX_CLASSIFIERS-1)
+ return;
+
+ pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex];
+ if (pstClassifierEntry) {
+ /* Store if Ipv6 */
+ pstClassifierEntry->bIpv6Protocol =
+ (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : false;
+
+ /* Destinaiton Port */
+ pstClassifierEntry->ucDestPortRangeLength =
+ pack_class_rule->u8ProtocolDestPortRangeLength / 4;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Destination Port Range Length:0x%X ",
+ pstClassifierEntry->ucDestPortRangeLength);
+
+ if (pack_class_rule->u8ProtocolDestPortRangeLength <= MAX_PORT_RANGE) {
+ for (i = 0; i < (pstClassifierEntry->ucDestPortRangeLength); i++) {
+ pstClassifierEntry->usDestPortRangeLo[i] =
+ *((PUSHORT)(pack_class_rule->u8ProtocolDestPortRange+i));
+ pstClassifierEntry->usDestPortRangeHi[i] =
+ *((PUSHORT)(pack_class_rule->u8ProtocolDestPortRange+2+i));
+ pstClassifierEntry->usDestPortRangeLo[i] =
+ ntohs(pstClassifierEntry->usDestPortRangeLo[i]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CONN_MSG, DBG_LVL_ALL,
+ "Destination Port Range Lo:0x%X ",
+ pstClassifierEntry->usDestPortRangeLo[i]);
+ pstClassifierEntry->usDestPortRangeHi[i] =
+ ntohs(pstClassifierEntry->usDestPortRangeHi[i]);
+ }
+ } else {
+ pstClassifierEntry->ucDestPortRangeLength = 0;
+ }
+
+ /* Source Port */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Source Port Range Length:0x%X ",
+ pack_class_rule->u8ProtocolSourcePortRangeLength);
+ if (pack_class_rule->u8ProtocolSourcePortRangeLength <= MAX_PORT_RANGE) {
+ pstClassifierEntry->ucSrcPortRangeLength =
+ pack_class_rule->u8ProtocolSourcePortRangeLength/4;
+ for (i = 0; i < (pstClassifierEntry->ucSrcPortRangeLength); i++) {
+ pstClassifierEntry->usSrcPortRangeLo[i] =
+ *((PUSHORT)(pack_class_rule->
+ u8ProtocolSourcePortRange+i));
+ pstClassifierEntry->usSrcPortRangeHi[i] =
+ *((PUSHORT)(pack_class_rule->
+ u8ProtocolSourcePortRange+2+i));
+ pstClassifierEntry->usSrcPortRangeLo[i] =
+ ntohs(pstClassifierEntry->usSrcPortRangeLo[i]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CONN_MSG, DBG_LVL_ALL,
+ "Source Port Range Lo:0x%X ",
+ pstClassifierEntry->usSrcPortRangeLo[i]);
+ pstClassifierEntry->usSrcPortRangeHi[i] =
+ ntohs(pstClassifierEntry->usSrcPortRangeHi[i]);
+ }
+ }
+ /* Destination Ip Address and Mask */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Ip Destination Parameters : ");
+ CopyIpAddrToClassifier(pstClassifierEntry,
+ pack_class_rule->u8IPDestinationAddressLength,
+ pack_class_rule->u8IPDestinationAddress,
+ (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ?
+ TRUE : false, eDestIpAddress);
+
+ /* Source Ip Address and Mask */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Ip Source Parameters : ");
+
+ CopyIpAddrToClassifier(pstClassifierEntry,
+ pack_class_rule->u8IPMaskedSourceAddressLength,
+ pack_class_rule->u8IPMaskedSourceAddress,
+ (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : false,
+ eSrcIpAddress);
+
+ /* TOS */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "TOS Length:0x%X ",
+ pack_class_rule->u8IPTypeOfServiceLength);
+ if (pack_class_rule->u8IPTypeOfServiceLength == 3) {
+ pstClassifierEntry->ucIPTypeOfServiceLength =
+ pack_class_rule->u8IPTypeOfServiceLength;
+ pstClassifierEntry->ucTosLow =
+ pack_class_rule->u8IPTypeOfService[0];
+ pstClassifierEntry->ucTosHigh =
+ pack_class_rule->u8IPTypeOfService[1];
+ pstClassifierEntry->ucTosMask =
+ pack_class_rule->u8IPTypeOfService[2];
+ pstClassifierEntry->bTOSValid = TRUE;
+ }
+ if (pack_class_rule->u8Protocol == 0) {
+ /* we didn't get protocol field filled in by the BS */
+ pstClassifierEntry->ucProtocolLength = 0;
+ } else {
+ pstClassifierEntry->ucProtocolLength = 1; /* 1 valid protocol */
+ }
+
+ pstClassifierEntry->ucProtocol[0] = pack_class_rule->u8Protocol;
+ pstClassifierEntry->u8ClassifierRulePriority =
+ pack_class_rule->u8ClassifierRulePriority;
+
+ /* store the classifier rule ID and set this classifier entry as valid */
+ pstClassifierEntry->ucDirection =
+ Adapter->PackInfo[uiSearchRuleIndex].ucDirection;
+ pstClassifierEntry->uiClassifierRuleIndex =
+ ntohs(pack_class_rule->u16PacketClassificationRuleIndex);
+ pstClassifierEntry->usVCID_Value =
+ Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value;
+ pstClassifierEntry->ulSFID =
+ Adapter->PackInfo[uiSearchRuleIndex].ulSFID;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Search Index %d Dir: %d, Index: %d, Vcid: %d\n",
+ uiSearchRuleIndex,
+ pstClassifierEntry->ucDirection,
+ pstClassifierEntry->uiClassifierRuleIndex,
+ pstClassifierEntry->usVCID_Value);
+
+ if (pack_class_rule->u8AssociatedPHSI)
+ pstClassifierEntry->u8AssociatedPHSI =
+ pack_class_rule->u8AssociatedPHSI;
+
+ /* Copy ETH CS Parameters */
+ pstClassifierEntry->ucEthCSSrcMACLen =
+ (pack_class_rule->u8EthernetSourceMACAddressLength);
+ memcpy(pstClassifierEntry->au8EThCSSrcMAC,
+ pack_class_rule->u8EthernetSourceMACAddress,
+ MAC_ADDRESS_SIZE);
+ memcpy(pstClassifierEntry->au8EThCSSrcMACMask,
+ pack_class_rule->u8EthernetSourceMACAddress
+ + MAC_ADDRESS_SIZE, MAC_ADDRESS_SIZE);
+ pstClassifierEntry->ucEthCSDestMACLen =
+ (pack_class_rule->u8EthernetDestMacAddressLength);
+ memcpy(pstClassifierEntry->au8EThCSDestMAC,
+ pack_class_rule->u8EthernetDestMacAddress,
+ MAC_ADDRESS_SIZE);
+ memcpy(pstClassifierEntry->au8EThCSDestMACMask,
+ pack_class_rule->u8EthernetDestMacAddress
+ + MAC_ADDRESS_SIZE, MAC_ADDRESS_SIZE);
+ pstClassifierEntry->ucEtherTypeLen =
+ (pack_class_rule->u8EthertypeLength);
+ memcpy(pstClassifierEntry->au8EthCSEtherType,
+ pack_class_rule->u8Ethertype,
+ NUM_ETHERTYPE_BYTES);
+ memcpy(pstClassifierEntry->usUserPriority,
+ &pack_class_rule->u16UserPriority, 2);
+ pstClassifierEntry->usVLANID =
+ ntohs(pack_class_rule->u16VLANID);
+ pstClassifierEntry->usValidityBitMap =
+ ntohs(pack_class_rule->u16ValidityBitMap);
+
+ pstClassifierEntry->bUsed = TRUE;
+ }
+}
+
+/*
+ * @ingroup ctrl_pkt_functions
+ */
+static inline VOID DeleteClassifierRuleFromSF(struct bcm_mini_adapter *Adapter,
+ UINT uiSearchRuleIndex, UINT nClassifierIndex)
+{
+ struct bcm_classifier_rule *pstClassifierEntry = NULL;
+ B_UINT16 u16PacketClassificationRuleIndex;
+ USHORT usVCID;
+ /* VOID *pvPhsContext = NULL; */
+ /*ULONG ulPhsStatus; */
+
+ usVCID = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value;
+
+ if (nClassifierIndex > MAX_CLASSIFIERS-1)
+ return;
+
+ if (usVCID == 0)
+ return;
+
+ u16PacketClassificationRuleIndex =
+ Adapter->astClassifierTable[nClassifierIndex].uiClassifierRuleIndex;
+ pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex];
+ if (pstClassifierEntry) {
+ pstClassifierEntry->bUsed = false;
+ pstClassifierEntry->uiClassifierRuleIndex = 0;
+ memset(pstClassifierEntry, 0,
+ sizeof(struct bcm_classifier_rule));
+
+ /* Delete the PHS Rule for this classifier */
+ PhsDeleteClassifierRule(&Adapter->stBCMPhsContext, usVCID,
+ u16PacketClassificationRuleIndex);
+ }
+}
+
+/*
+ * @ingroup ctrl_pkt_functions
+ */
+VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter,
+ UINT uiSearchRuleIndex)
+{
+ struct bcm_classifier_rule *pstClassifierEntry = NULL;
+ int i;
+ /* B_UINT16 u16PacketClassificationRuleIndex; */
+ USHORT ulVCID;
+ /* VOID *pvPhsContext = NULL; */
+ /* ULONG ulPhsStatus; */
+
+ ulVCID = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value;
+
+ if (ulVCID == 0)
+ return;
+
+ for (i = 0; i < MAX_CLASSIFIERS; i++) {
+ if (Adapter->astClassifierTable[i].usVCID_Value == ulVCID) {
+ pstClassifierEntry = &Adapter->astClassifierTable[i];
+
+ if (pstClassifierEntry->bUsed)
+ DeleteClassifierRuleFromSF(Adapter,
+ uiSearchRuleIndex, i);
+ }
+ }
+
+ /* Delete All Phs Rules Associated with this SF */
+ PhsDeleteSFRules(&Adapter->stBCMPhsContext, ulVCID);
+}
+
+/*
+ * This routinue copies the Connection Management
+ * related data into the Adapter structure.
+ * @ingroup ctrl_pkt_functions
+ */
+static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer to the Adapter structure */
+ register struct bcm_connect_mgr_params *psfLocalSet, /* Pointer to the connection manager parameters structure */
+ register UINT uiSearchRuleIndex, /* <Index of Queue, to which this data belongs */
+ register UCHAR ucDsxType,
+ struct bcm_add_indication_alt *pstAddIndication) {
+
+ /* UCHAR ucProtocolLength = 0; */
+ ULONG ulSFID;
+ UINT nClassifierIndex = 0;
+ enum E_CLASSIFIER_ACTION eClassifierAction = eInvalidClassifierAction;
+ B_UINT16 u16PacketClassificationRuleIndex = 0;
+ int i;
+ struct bcm_convergence_types *psfCSType = NULL;
+ struct bcm_phs_rule sPhsRule;
+ struct bcm_packet_info *curr_packinfo =
+ &Adapter->PackInfo[uiSearchRuleIndex];
+ USHORT uVCID = curr_packinfo->usVCID_Value;
+ UINT UGIValue = 0;
+
+ curr_packinfo->bValid = TRUE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Search Rule Index = %d\n", uiSearchRuleIndex);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "%s: SFID= %x ", __func__, ntohl(psfLocalSet->u32SFID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Updating Queue %d", uiSearchRuleIndex);
+
+ ulSFID = ntohl(psfLocalSet->u32SFID);
+ /* Store IP Version used */
+ /* Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF */
+
+ curr_packinfo->bIPCSSupport = 0;
+ curr_packinfo->bEthCSSupport = 0;
+
+ /* Enable IP/ETh CS Support As Required */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "CopyToAdapter : u8CSSpecification : %X\n",
+ psfLocalSet->u8CSSpecification);
+ switch (psfLocalSet->u8CSSpecification) {
+ case eCSPacketIPV4:
+ curr_packinfo->bIPCSSupport = IPV4_CS;
+ break;
+ case eCSPacketIPV6:
+ curr_packinfo->bIPCSSupport = IPV6_CS;
+ break;
+ case eCS802_3PacketEthernet:
+ case eCS802_1QPacketVLAN:
+ curr_packinfo->bEthCSSupport = ETH_CS_802_3;
+ break;
+ case eCSPacketIPV4Over802_1QVLAN:
+ case eCSPacketIPV4Over802_3Ethernet:
+ curr_packinfo->bIPCSSupport = IPV4_CS;
+ curr_packinfo->bEthCSSupport = ETH_CS_802_3;
+ break;
+ case eCSPacketIPV6Over802_1QVLAN:
+ case eCSPacketIPV6Over802_3Ethernet:
+ curr_packinfo->bIPCSSupport = IPV6_CS;
+ curr_packinfo->bEthCSSupport = ETH_CS_802_3;
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Error in value of CS Classification.. setting default to IP CS\n");
+ curr_packinfo->bIPCSSupport = IPV4_CS;
+ break;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "CopyToAdapter : Queue No : %X ETH CS Support : %X , IP CS Support : %X\n",
+ uiSearchRuleIndex,
+ curr_packinfo->bEthCSSupport,
+ curr_packinfo->bIPCSSupport);
+
+ /* Store IP Version used */
+ /* Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF */
+ if (curr_packinfo->bIPCSSupport == IPV6_CS)
+ curr_packinfo->ucIpVersion = IPV6;
+ else
+ curr_packinfo->ucIpVersion = IPV4;
+
+ /* To ensure that the ETH CS code doesn't gets executed if the BS doesn't supports ETH CS */
+ if (!Adapter->bETHCSEnabled)
+ curr_packinfo->bEthCSSupport = 0;
+
+ if (psfLocalSet->u8ServiceClassNameLength > 0 && psfLocalSet->u8ServiceClassNameLength < 32)
+ memcpy(curr_packinfo->ucServiceClassName,
+ psfLocalSet->u8ServiceClassName,
+ psfLocalSet->u8ServiceClassNameLength);
+
+ curr_packinfo->u8QueueType = psfLocalSet->u8ServiceFlowSchedulingType;
+
+ if (curr_packinfo->u8QueueType == BE && curr_packinfo->ucDirection)
+ Adapter->usBestEffortQueueIndex = uiSearchRuleIndex;
+
+ curr_packinfo->ulSFID = ntohl(psfLocalSet->u32SFID);
+
+ curr_packinfo->u8TrafficPriority = psfLocalSet->u8TrafficPriority;
+
+ /* copy all the classifier in the Service Flow param structure */
+ for (i = 0; i < psfLocalSet->u8TotalClassifiers; i++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Classifier index =%d", i);
+ psfCSType = &psfLocalSet->cConvergenceSLTypes[i];
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Classifier index =%d", i);
+
+ if (psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority)
+ curr_packinfo->bClassifierPriority = TRUE;
+
+ if (psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority)
+ curr_packinfo->bClassifierPriority = TRUE;
+
+ if (ucDsxType == DSA_ACK) {
+ eClassifierAction = eAddClassifier;
+ } else if (ucDsxType == DSC_ACK) {
+ switch (psfCSType->u8ClassfierDSCAction) {
+ case 0: /* DSC Add Classifier */
+ eClassifierAction = eAddClassifier;
+ break;
+ case 1: /* DSC Replace Classifier */
+ eClassifierAction = eReplaceClassifier;
+ break;
+ case 2: /* DSC Delete Classifier */
+ eClassifierAction = eDeleteClassifier;
+ break;
+ default:
+ eClassifierAction = eInvalidClassifierAction;
+ }
+ }
+
+ u16PacketClassificationRuleIndex = ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex);
+
+ switch (eClassifierAction) {
+ case eAddClassifier:
+ /* Get a Free Classifier Index From Classifier table for this SF to add the Classifier */
+ /* Contained in this message */
+ nClassifierIndex = SearchClsid(Adapter,
+ ulSFID,
+ u16PacketClassificationRuleIndex);
+
+ if (nClassifierIndex > MAX_CLASSIFIERS) {
+ nClassifierIndex = SearchFreeClsid(Adapter);
+ if (nClassifierIndex > MAX_CLASSIFIERS) {
+ /* Failed To get a free Entry */
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ CONN_MSG,
+ DBG_LVL_ALL,
+ "Error Failed To get a free Classifier Entry");
+ break;
+ }
+ /* Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. */
+ CopyClassifierRuleToSF(Adapter, psfCSType,
+ uiSearchRuleIndex,
+ nClassifierIndex);
+ } else {
+ /* This Classifier Already Exists and it is invalid to Add Classifier with existing PCRI */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CONN_MSG,
+ DBG_LVL_ALL,
+ "CopyToAdapter: Error The Specified Classifier Already Exists and attempted To Add Classifier with Same PCRI : 0x%x\n",
+ u16PacketClassificationRuleIndex);
+ }
+ break;
+ case eReplaceClassifier:
+ /* Get the Classifier Index From Classifier table for this SF and replace existing Classifier */
+ /* with the new classifier Contained in this message */
+ nClassifierIndex = SearchClsid(Adapter, ulSFID,
+ u16PacketClassificationRuleIndex);
+ if (nClassifierIndex > MAX_CLASSIFIERS) {
+ /* Failed To search the classifier */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CONN_MSG, DBG_LVL_ALL,
+ "Error Search for Classifier To be replaced failed");
+ break;
+ }
+ /* Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. */
+ CopyClassifierRuleToSF(Adapter, psfCSType,
+ uiSearchRuleIndex, nClassifierIndex);
+ break;
+ case eDeleteClassifier:
+ /* Get the Classifier Index From Classifier table for this SF and replace existing Classifier */
+ /* with the new classifier Contained in this message */
+ nClassifierIndex = SearchClsid(Adapter, ulSFID,
+ u16PacketClassificationRuleIndex);
+ if (nClassifierIndex > MAX_CLASSIFIERS) {
+ /* Failed To search the classifier */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CONN_MSG, DBG_LVL_ALL,
+ "Error Search for Classifier To be deleted failed");
+ break;
+ }
+
+ /* Delete This classifier */
+ DeleteClassifierRuleFromSF(Adapter, uiSearchRuleIndex,
+ nClassifierIndex);
+ break;
+ default:
+ /* Invalid Action for classifier */
+ break;
+ }
+ }
+
+ /* Repeat parsing Classification Entries to process PHS Rules */
+ for (i = 0; i < psfLocalSet->u8TotalClassifiers; i++) {
+ psfCSType = &psfLocalSet->cConvergenceSLTypes[i];
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "psfCSType->u8PhsDSCAction : 0x%x\n",
+ psfCSType->u8PhsDSCAction);
+
+ switch (psfCSType->u8PhsDSCAction) {
+ case eDeleteAllPHSRules:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL,
+ "Deleting All PHS Rules For VCID: 0x%X\n",
+ uVCID);
+
+ /* Delete All the PHS rules for this Service flow */
+ PhsDeleteSFRules(&Adapter->stBCMPhsContext, uVCID);
+ break;
+ case eDeletePHSRule:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL,
+ "PHS DSC Action = Delete PHS Rule\n");
+
+ if (psfCSType->cPhsRule.u8PHSI)
+ PhsDeletePHSRule(&Adapter->stBCMPhsContext,
+ uVCID,
+ psfCSType->cCPacketClassificationRule.u8AssociatedPHSI);
+
+ break;
+ default:
+ if (ucDsxType == DSC_ACK) {
+ /* BCM_DEBUG_PRINT(CONN_MSG,("Invalid PHS DSC Action For DSC\n",psfCSType->cPhsRule.u8PHSI)); */
+ break; /* FOr DSC ACK Case PHS DSC Action must be in valid set */
+ }
+ /* Proceed To Add PHS rule for DSA_ACK case even if PHS DSC action is unspecified */
+ /* No Break Here . Intentionally! */
+
+ case eAddPHSRule:
+ case eSetPHSRule:
+ if (psfCSType->cPhsRule.u8PHSI) {
+ /* Apply This PHS Rule to all classifiers whose Associated PHSI Match */
+ apply_phs_rule_to_all_classifiers(Adapter,
+ uiSearchRuleIndex,
+ uVCID,
+ &sPhsRule,
+ &psfCSType->cPhsRule,
+ pstAddIndication);
+ }
+ break;
+ }
+ }
+
+ if (psfLocalSet->u32MaxSustainedTrafficRate == 0) {
+ /* No Rate Limit . Set Max Sustained Traffic Rate to Maximum */
+ curr_packinfo->uiMaxAllowedRate = WIMAX_MAX_ALLOWED_RATE;
+ } else if (ntohl(psfLocalSet->u32MaxSustainedTrafficRate) > WIMAX_MAX_ALLOWED_RATE) {
+ /* Too large Allowed Rate specified. Limiting to Wi Max Allowed rate */
+ curr_packinfo->uiMaxAllowedRate = WIMAX_MAX_ALLOWED_RATE;
+ } else {
+ curr_packinfo->uiMaxAllowedRate =
+ ntohl(psfLocalSet->u32MaxSustainedTrafficRate);
+ }
+
+ curr_packinfo->uiMaxLatency = ntohl(psfLocalSet->u32MaximumLatency);
+ if (curr_packinfo->uiMaxLatency == 0) /* 0 should be treated as infinite */
+ curr_packinfo->uiMaxLatency = MAX_LATENCY_ALLOWED;
+
+ if ((curr_packinfo->u8QueueType == ERTPS ||
+ curr_packinfo->u8QueueType == UGS))
+ UGIValue = ntohs(psfLocalSet->u16UnsolicitedGrantInterval);
+
+ if (UGIValue == 0)
+ UGIValue = DEFAULT_UG_INTERVAL;
+
+ /*
+ * For UGI based connections...
+ * DEFAULT_UGI_FACTOR*UGIInterval worth of data is the max token count at host...
+ * The extra amount of token is to ensure that a large amount of jitter won't have loss in throughput...
+ * In case of non-UGI based connection, 200 frames worth of data is the max token count at host...
+ */
+ curr_packinfo->uiMaxBucketSize =
+ (DEFAULT_UGI_FACTOR*curr_packinfo->uiMaxAllowedRate*UGIValue)/1000;
+
+ if (curr_packinfo->uiMaxBucketSize < WIMAX_MAX_MTU*8) {
+ UINT UGIFactor = 0;
+ /* Special Handling to ensure the biggest size of packet can go out from host to FW as follows:
+ * 1. Any packet from Host to FW can go out in different packet size.
+ * 2. So in case the Bucket count is smaller than MTU, the packets of size (Size > TokenCount), will get dropped.
+ * 3. We can allow packets of MaxSize from Host->FW that can go out from FW in multiple SDUs by fragmentation at Wimax Layer
+ */
+ UGIFactor = (curr_packinfo->uiMaxLatency/UGIValue + 1);
+
+ if (UGIFactor > DEFAULT_UGI_FACTOR)
+ curr_packinfo->uiMaxBucketSize =
+ (UGIFactor*curr_packinfo->uiMaxAllowedRate*UGIValue)/1000;
+
+ if (curr_packinfo->uiMaxBucketSize > WIMAX_MAX_MTU*8)
+ curr_packinfo->uiMaxBucketSize = WIMAX_MAX_MTU*8;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "LAT: %d, UGI: %d\n", curr_packinfo->uiMaxLatency,
+ UGIValue);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "uiMaxAllowedRate: 0x%x, u32MaxSustainedTrafficRate: 0x%x ,uiMaxBucketSize: 0x%x",
+ curr_packinfo->uiMaxAllowedRate,
+ ntohl(psfLocalSet->u32MaxSustainedTrafficRate),
+ curr_packinfo->uiMaxBucketSize);
+
+ /* copy the extended SF Parameters to Support MIBS */
+ CopyMIBSExtendedSFParameters(Adapter, psfLocalSet, uiSearchRuleIndex);
+
+ /* store header suppression enabled flag per SF */
+ curr_packinfo->bHeaderSuppressionEnabled =
+ !(psfLocalSet->u8RequesttransmissionPolicy &
+ MASK_DISABLE_HEADER_SUPPRESSION);
+
+ kfree(curr_packinfo->pstSFIndication);
+ curr_packinfo->pstSFIndication = pstAddIndication;
+
+ /* Re Sort the SF list in PackInfo according to Traffic Priority */
+ SortPackInfo(Adapter);
+
+ /* Re Sort the Classifier Rules table and re - arrange
+ * according to Classifier Rule Priority
+ */
+ SortClassifiers(Adapter);
+ DumpPhsRules(&Adapter->stBCMPhsContext);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "%s <=====", __func__);
+}
+
+/***********************************************************************
+ * Function - DumpCmControlPacket
+ *
+ * Description - This routinue Dumps the Contents of the AddIndication
+ * Structure in the Connection Management Control Packet
+ *
+ * Parameter - pvBuffer: Pointer to the buffer containing the
+ * AddIndication data.
+ *
+ * Returns - None
+ *************************************************************************/
+static VOID DumpCmControlPacket(PVOID pvBuffer)
+{
+ int uiLoopIndex;
+ int nIndex;
+ struct bcm_add_indication_alt *pstAddIndication;
+ UINT nCurClassifierCnt;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ pstAddIndication = pvBuffer;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "======>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Type: 0x%X", pstAddIndication->u8Type);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Direction: 0x%X", pstAddIndication->u8Direction);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TID: 0x%X", ntohs(pstAddIndication->u16TID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", ntohs(pstAddIndication->u16CID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VCID: 0x%X", ntohs(pstAddIndication->u16VCID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " AuthorizedSet--->");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", htonl(pstAddIndication->sfAuthorizedSet.u32SFID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", htons(pstAddIndication->sfAuthorizedSet.u16CID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassNameLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x%X ,0x%X , 0x%X, 0x%X, 0x%X, 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassName[0],
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassName[1],
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassName[2],
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassName[3],
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassName[4],
+ pstAddIndication->sfAuthorizedSet.u8ServiceClassName[5]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%X", pstAddIndication->sfAuthorizedSet.u8MBSService);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%X", pstAddIndication->sfAuthorizedSet.u8QosParamSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority: 0x%X, %p",
+ pstAddIndication->sfAuthorizedSet.u8TrafficPriority, &pstAddIndication->sfAuthorizedSet.u8TrafficPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxSustainedTrafficRate: 0x%X 0x%p",
+ pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate,
+ &pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst: 0x%X", pstAddIndication->sfAuthorizedSet.u32MaxTrafficBurst);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X",
+ pstAddIndication->sfAuthorizedSet.u32MinReservedTrafficRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParamLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParam[0]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8ServiceFlowSchedulingType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter: 0x%X", pstAddIndication->sfAuthorizedSet.u32ToleratedJitter);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency: 0x%X", pstAddIndication->sfAuthorizedSet.u32MaximumLatency);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8FixedLengthVSVariableLengthSDUIndicator);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize: 0x%X", pstAddIndication->sfAuthorizedSet.u8SDUSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID: 0x%X", pstAddIndication->sfAuthorizedSet.u16TargetSAID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable: 0x%X", pstAddIndication->sfAuthorizedSet.u8ARQEnable);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQWindowSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQRetryTxTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQRetryRxTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQBlockLifeTime);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQSyncLossTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder: 0x%X", pstAddIndication->sfAuthorizedSet.u8ARQDeliverInOrder);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQRxPurgeTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQBlockSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification: 0x%X", pstAddIndication->sfAuthorizedSet.u8CSSpecification);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8TypeOfDataDeliveryService);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime: 0x%X", pstAddIndication->sfAuthorizedSet.u16SDUInterArrivalTime);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase: 0x%X", pstAddIndication->sfAuthorizedSet.u16TimeBase);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference: 0x%X", pstAddIndication->sfAuthorizedSet.u8PagingPreference);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UnsolicitedPollingInterval: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u16UnsolicitedPollingInterval);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "sfAuthorizedSet.u8HARQChannelMapping %x %x %x ",
+ *(unsigned int *)pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping,
+ *(unsigned int *)&pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[4],
+ *(USHORT *)&pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[8]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference: 0x%X",
+ pstAddIndication->sfAuthorizedSet.u8TrafficIndicationPreference);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received: 0x%X", pstAddIndication->sfAuthorizedSet.u8TotalClassifiers);
+
+ nCurClassifierCnt = pstAddIndication->sfAuthorizedSet.u8TotalClassifiers;
+ if (nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF)
+ nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.bValid %d", pstAddIndication->sfAuthorizedSet.bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.u16MacOverhead %x", pstAddIndication->sfAuthorizedSet.u16MacOverhead);
+ if (!pstAddIndication->sfAuthorizedSet.bValid)
+ pstAddIndication->sfAuthorizedSet.bValid = 1;
+ for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) {
+ struct bcm_convergence_types *psfCSType = NULL;
+ psfCSType = &pstAddIndication->sfAuthorizedSet.cConvergenceSLTypes[nIndex];
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "psfCSType = %p", psfCSType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "CCPacketClassificationRuleSI====>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%X ,0x%X ,0x%X ",
+ psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0],
+ psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1],
+ psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8Protocol);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32]: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength:0x%X ",
+ psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0],
+ psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1],
+ psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2],
+ psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0],
+ psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1],
+ psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2],
+ psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: %pM",
+ psfCSType->cCPacketClassificationRule.
+ u8EthernetDestMacAddress);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: %pM",
+ psfCSType->cCPacketClassificationRule.
+ u8EthernetSourceMACAddress);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8EthertypeLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3]: 0x%02X ,0x%02X ,0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8Ethertype[0],
+ psfCSType->cCPacketClassificationRule.u8Ethertype[1],
+ psfCSType->cCPacketClassificationRule.u8Ethertype[2]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority: 0x%X ", psfCSType->cCPacketClassificationRule.u16UserPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI: 0x%02X ", psfCSType->cCPacketClassificationRule.u8AssociatedPHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1]: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]);
+#ifdef VERSION_D5
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x%*ph ",
+ 6, psfCSType->cCPacketClassificationRule.
+ u8IPv6FlowLable);
+#endif
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid: 0x%02X", pstAddIndication->sfAuthorizedSet.bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "AdmittedSet--->");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", pstAddIndication->sfAdmittedSet.u32SFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfAdmittedSet.u16CID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X",
+ pstAddIndication->sfAdmittedSet.u8ServiceClassNameLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,
+ "u8ServiceClassName: 0x%*ph",
+ 6, pstAddIndication->sfAdmittedSet.u8ServiceClassName);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfAdmittedSet.u8MBSService);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfAdmittedSet.u8QosParamSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority: 0x%02X", pstAddIndication->sfAdmittedSet.u8TrafficPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst: 0x%X", pstAddIndication->sfAdmittedSet.u32MaxTrafficBurst);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate: 0x%X",
+ pstAddIndication->sfAdmittedSet.u32MinReservedTrafficRate);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength: 0x%02X",
+ pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParamLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam: 0x%02X",
+ pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParam[0]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType: 0x%02X",
+ pstAddIndication->sfAdmittedSet.u8ServiceFlowSchedulingType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter: 0x%X", pstAddIndication->sfAdmittedSet.u32ToleratedJitter);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency: 0x%X", pstAddIndication->sfAdmittedSet.u32MaximumLatency);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X",
+ pstAddIndication->sfAdmittedSet.u8FixedLengthVSVariableLengthSDUIndicator);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize: 0x%02X", pstAddIndication->sfAdmittedSet.u8SDUSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID: 0x%02X", pstAddIndication->sfAdmittedSet.u16TargetSAID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable: 0x%02X", pstAddIndication->sfAdmittedSet.u8ARQEnable);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQWindowSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQRetryTxTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQRetryRxTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQBlockLifeTime);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQSyncLossTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder: 0x%02X", pstAddIndication->sfAdmittedSet.u8ARQDeliverInOrder);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQRxPurgeTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQBlockSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification: 0x%02X", pstAddIndication->sfAdmittedSet.u8CSSpecification);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService: 0x%02X",
+ pstAddIndication->sfAdmittedSet.u8TypeOfDataDeliveryService);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime: 0x%X", pstAddIndication->sfAdmittedSet.u16SDUInterArrivalTime);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase: 0x%X", pstAddIndication->sfAdmittedSet.u16TimeBase);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference: 0x%X", pstAddIndication->sfAdmittedSet.u8PagingPreference);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference: 0x%02X",
+ pstAddIndication->sfAdmittedSet.u8TrafficIndicationPreference);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received: 0x%X", pstAddIndication->sfAdmittedSet.u8TotalClassifiers);
+
+ nCurClassifierCnt = pstAddIndication->sfAdmittedSet.u8TotalClassifiers;
+ if (nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF)
+ nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF;
+
+ for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) {
+ struct bcm_convergence_types *psfCSType = NULL;
+
+ psfCSType = &pstAddIndication->sfAdmittedSet.cConvergenceSLTypes[nIndex];
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength: 0x%02X",
+ psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%*ph",
+ 3, psfCSType->cCPacketClassificationRule.
+ u8IPTypeOfService);
+ for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", psfCSType->cCPacketClassificationRule.u8Protocol);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32]: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x%*ph ",
+ 4, psfCSType->cCPacketClassificationRule.
+ u8ProtocolSourcePortRange);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x%*ph ",
+ 4, psfCSType->cCPacketClassificationRule.
+ u8ProtocolDestPortRange);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: %pM",
+ psfCSType->cCPacketClassificationRule.
+ u8EthernetDestMacAddress);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: %pM",
+ psfCSType->cCPacketClassificationRule.
+ u8EthernetSourceMACAddress);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthertypeLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8Ethertype[3]: 0x%*ph",
+ 3, psfCSType->cCPacketClassificationRule.
+ u8Ethertype);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority: 0x%X ", psfCSType->cCPacketClassificationRule.u16UserPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI: 0x%02X ", psfCSType->cCPacketClassificationRule.u8AssociatedPHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength: 0x%02X",
+ psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1]: 0x%02X ",
+ psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]);
+#ifdef VERSION_D5
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ",
+ psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x%*ph ",
+ 6, psfCSType->cCPacketClassificationRule.
+ u8IPv6FlowLable);
+#endif
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid: 0x%X", pstAddIndication->sfAdmittedSet.bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " ActiveSet--->");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", pstAddIndication->sfActiveSet.u32SFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfActiveSet.u16CID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", pstAddIndication->sfActiveSet.u8ServiceClassNameLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,
+ "u8ServiceClassName: 0x%*ph",
+ 6, pstAddIndication->sfActiveSet.u8ServiceClassName);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfActiveSet.u8MBSService);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfActiveSet.u8QosParamSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority: 0x%02X", pstAddIndication->sfActiveSet.u8TrafficPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst: 0x%X", pstAddIndication->sfActiveSet.u32MaxTrafficBurst);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate: 0x%X",
+ pstAddIndication->sfActiveSet.u32MinReservedTrafficRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength: 0x%02X",
+ pstAddIndication->sfActiveSet.u8VendorSpecificQoSParamLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam: 0x%02X",
+ pstAddIndication->sfActiveSet.u8VendorSpecificQoSParam[0]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType: 0x%02X",
+ pstAddIndication->sfActiveSet.u8ServiceFlowSchedulingType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter: 0x%X", pstAddIndication->sfActiveSet.u32ToleratedJitter);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency: 0x%X", pstAddIndication->sfActiveSet.u32MaximumLatency);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X",
+ pstAddIndication->sfActiveSet.u8FixedLengthVSVariableLengthSDUIndicator);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize: 0x%X", pstAddIndication->sfActiveSet.u8SDUSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TargetSAID: 0x%X", pstAddIndication->sfActiveSet.u16TargetSAID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQEnable: 0x%X", pstAddIndication->sfActiveSet.u8ARQEnable);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQWindowSize: 0x%X", pstAddIndication->sfActiveSet.u16ARQWindowSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryTxTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQRetryTxTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryRxTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQRetryRxTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockLifeTime: 0x%X", pstAddIndication->sfActiveSet.u16ARQBlockLifeTime);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQSyncLossTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQSyncLossTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQDeliverInOrder: 0x%X", pstAddIndication->sfActiveSet.u8ARQDeliverInOrder);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRxPurgeTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQRxPurgeTimeOut);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockSize: 0x%X", pstAddIndication->sfActiveSet.u16ARQBlockSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8CSSpecification: 0x%X", pstAddIndication->sfActiveSet.u8CSSpecification);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TypeOfDataDeliveryService: 0x%X",
+ pstAddIndication->sfActiveSet.u8TypeOfDataDeliveryService);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16SDUInterArrivalTime: 0x%X", pstAddIndication->sfActiveSet.u16SDUInterArrivalTime);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TimeBase: 0x%X", pstAddIndication->sfActiveSet.u16TimeBase);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8PagingPreference: 0x%X", pstAddIndication->sfActiveSet.u8PagingPreference);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TrafficIndicationPreference: 0x%X",
+ pstAddIndication->sfActiveSet.u8TrafficIndicationPreference);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received: 0x%X", pstAddIndication->sfActiveSet.u8TotalClassifiers);
+
+ nCurClassifierCnt = pstAddIndication->sfActiveSet.u8TotalClassifiers;
+ if (nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF)
+ nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF;
+
+ for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) {
+ struct bcm_convergence_types *psfCSType = NULL;
+ struct bcm_packet_class_rules *clsRule = NULL;
+
+ psfCSType = &pstAddIndication->sfActiveSet.cConvergenceSLTypes[nIndex];
+ clsRule = &psfCSType->cCPacketClassificationRule;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " CCPacketClassificationRuleSI====>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u8ClassifierRulePriority: 0x%X ",
+ clsRule->u8ClassifierRulePriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u8IPTypeOfServiceLength: 0x%X ",
+ clsRule->u8IPTypeOfServiceLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8IPTypeOfService[3]: 0x%X ,0x%X ,0x%X ",
+ clsRule->u8IPTypeOfService[0],
+ clsRule->u8IPTypeOfService[1],
+ clsRule->u8IPTypeOfService[2]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8Protocol: 0x%X ",
+ clsRule->u8Protocol);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ "u8IPMaskedSourceAddressLength: 0x%X ",
+ clsRule->u8IPMaskedSourceAddressLength);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ "u8IPMaskedSourceAddress[32]: 0x%X ",
+ clsRule->u8IPMaskedSourceAddress[uiLoopIndex]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ "u8IPDestinationAddressLength: 0x%02X ",
+ clsRule->u8IPDestinationAddressLength);
+
+ for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8IPDestinationAddress[32]:0x%X ",
+ clsRule->u8IPDestinationAddress[uiLoopIndex]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8ProtocolSourcePortRangeLength: 0x%X ",
+ clsRule->u8ProtocolSourcePortRangeLength);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8ProtocolSourcePortRange[4]: 0x%X ,0x%X ,0x%X ,0x%X ",
+ clsRule->u8ProtocolSourcePortRange[0],
+ clsRule->u8ProtocolSourcePortRange[1],
+ clsRule->u8ProtocolSourcePortRange[2],
+ clsRule->u8ProtocolSourcePortRange[3]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8ProtocolDestPortRangeLength: 0x%X ",
+ clsRule->u8ProtocolDestPortRangeLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8ProtocolDestPortRange[4]: 0x%X ,0x%X ,0x%X ,0x%X ",
+ clsRule->u8ProtocolDestPortRange[0],
+ clsRule->u8ProtocolDestPortRange[1],
+ clsRule->u8ProtocolDestPortRange[2],
+ clsRule->u8ProtocolDestPortRange[3]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8EthernetDestMacAddressLength: 0x%X ",
+ clsRule->u8EthernetDestMacAddressLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8EthernetDestMacAddress[6]: 0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X",
+ clsRule->u8EthernetDestMacAddress[0],
+ clsRule->u8EthernetDestMacAddress[1],
+ clsRule->u8EthernetDestMacAddress[2],
+ clsRule->u8EthernetDestMacAddress[3],
+ clsRule->u8EthernetDestMacAddress[4],
+ clsRule->u8EthernetDestMacAddress[5]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8EthernetSourceMACAddressLength: 0x%X ",
+ clsRule->u8EthernetDestMacAddressLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ "u8EthernetSourceMACAddress[6]: 0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X",
+ clsRule->u8EthernetSourceMACAddress[0],
+ clsRule->u8EthernetSourceMACAddress[1],
+ clsRule->u8EthernetSourceMACAddress[2],
+ clsRule->u8EthernetSourceMACAddress[3],
+ clsRule->u8EthernetSourceMACAddress[4],
+ clsRule->u8EthernetSourceMACAddress[5]);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u8EthertypeLength: 0x%X ",
+ clsRule->u8EthertypeLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8Ethertype[3]: 0x%X ,0x%X ,0x%X ",
+ clsRule->u8Ethertype[0],
+ clsRule->u8Ethertype[1],
+ clsRule->u8Ethertype[2]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u16UserPriority: 0x%X ",
+ clsRule->u16UserPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u16VLANID: 0x%X ",
+ clsRule->u16VLANID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u8AssociatedPHSI: 0x%X ",
+ clsRule->u8AssociatedPHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u16PacketClassificationRuleIndex:0x%X ",
+ clsRule->u16PacketClassificationRuleIndex);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8VendorSpecificClassifierParamLength:0x%X ",
+ clsRule->u8VendorSpecificClassifierParamLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8VendorSpecificClassifierParam[1]:0x%X ",
+ clsRule->u8VendorSpecificClassifierParam[0]);
+#ifdef VERSION_D5
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, " u8IPv6FlowLableLength: 0x%X ",
+ clsRule->u8IPv6FlowLableLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL,
+ " u8IPv6FlowLable[6]: 0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X ",
+ clsRule->u8IPv6FlowLable[0],
+ clsRule->u8IPv6FlowLable[1],
+ clsRule->u8IPv6FlowLable[2],
+ clsRule->u8IPv6FlowLable[3],
+ clsRule->u8IPv6FlowLable[4],
+ clsRule->u8IPv6FlowLable[5]);
+#endif
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,
+ " bValid: 0x%X", pstAddIndication->sfActiveSet.bValid);
+}
+
+static inline ULONG RestoreSFParam(struct bcm_mini_adapter *Adapter,
+ ULONG ulAddrSFParamSet, PUCHAR pucDestBuffer)
+{
+ UINT nBytesToRead = sizeof(struct bcm_connect_mgr_params);
+
+ if (ulAddrSFParamSet == 0 || NULL == pucDestBuffer) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Got Param address as 0!!");
+ return 0;
+ }
+ ulAddrSFParamSet = ntohl(ulAddrSFParamSet);
+
+ /* Read out the SF Param Set At the indicated Location */
+ if (rdm(Adapter, ulAddrSFParamSet,(PUCHAR)pucDestBuffer, nBytesToRead) < 0)
+ return STATUS_FAILURE;
+
+ return 1;
+}
+
+static ULONG StoreSFParam(struct bcm_mini_adapter *Adapter, PUCHAR pucSrcBuffer,
+ ULONG ulAddrSFParamSet)
+{
+ UINT nBytesToWrite = sizeof(struct bcm_connect_mgr_params);
+ int ret = 0;
+
+ if (ulAddrSFParamSet == 0 || NULL == pucSrcBuffer)
+ return 0;
+
+ ret = wrm(Adapter, ulAddrSFParamSet, (u8 *)pucSrcBuffer, nBytesToWrite);
+ if (ret < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "%s:%d WRM failed", __func__, __LINE__);
+ return ret;
+ }
+ return 1;
+}
+
+ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter,
+ PVOID pvBuffer, UINT *puBufferLength)
+{
+ struct bcm_add_indication_alt *pstAddIndicationAlt = NULL;
+ struct bcm_add_indication *pstAddIndication = NULL;
+ struct bcm_del_request *pstDeletionRequest;
+ UINT uiSearchRuleIndex;
+ ULONG ulSFID;
+
+ pstAddIndicationAlt = pvBuffer;
+
+ /*
+ * In case of DSD Req By MS, we should immediately delete this SF so that
+ * we can stop the further classifying the pkt for this SF.
+ */
+ if (pstAddIndicationAlt->u8Type == DSD_REQ) {
+ pstDeletionRequest = pvBuffer;
+
+ ulSFID = ntohl(pstDeletionRequest->u32SFID);
+ uiSearchRuleIndex = SearchSfid(Adapter, ulSFID);
+
+ if (uiSearchRuleIndex < NO_OF_QUEUES) {
+ deleteSFBySfid(Adapter, uiSearchRuleIndex);
+ Adapter->u32TotalDSD++;
+ }
+ return 1;
+ }
+
+ if ((pstAddIndicationAlt->u8Type == DSD_RSP) ||
+ (pstAddIndicationAlt->u8Type == DSD_ACK)) {
+ /* No Special handling send the message as it is */
+ return 1;
+ }
+ /* For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver! */
+
+ pstAddIndication = kmalloc(sizeof(struct bcm_add_indication),
+ GFP_KERNEL);
+ if (pstAddIndication == NULL)
+ return 0;
+
+ /* AUTHORIZED SET */
+ pstAddIndication->psfAuthorizedSet = (struct bcm_connect_mgr_params *)
+ GetNextTargetBufferLocation(Adapter,
+ pstAddIndicationAlt->u16TID);
+ if (!pstAddIndication->psfAuthorizedSet) {
+ kfree(pstAddIndication);
+ return 0;
+ }
+
+ if (StoreSFParam(Adapter, (PUCHAR)&pstAddIndicationAlt->sfAuthorizedSet,
+ (ULONG)pstAddIndication->psfAuthorizedSet) != 1) {
+ kfree(pstAddIndication);
+ return 0;
+ }
+
+ /* this can't possibly be right */
+ pstAddIndication->psfAuthorizedSet =
+ (struct bcm_connect_mgr_params *) ntohl(
+ (ULONG)pstAddIndication->psfAuthorizedSet);
+
+ if (pstAddIndicationAlt->u8Type == DSA_REQ) {
+ struct bcm_add_request AddRequest;
+
+ AddRequest.u8Type = pstAddIndicationAlt->u8Type;
+ AddRequest.eConnectionDir = pstAddIndicationAlt->u8Direction;
+ AddRequest.u16TID = pstAddIndicationAlt->u16TID;
+ AddRequest.u16CID = pstAddIndicationAlt->u16CID;
+ AddRequest.u16VCID = pstAddIndicationAlt->u16VCID;
+ AddRequest.psfParameterSet = pstAddIndication->psfAuthorizedSet;
+ (*puBufferLength) = sizeof(struct bcm_add_request);
+ memcpy(pvBuffer, &AddRequest, sizeof(struct bcm_add_request));
+ kfree(pstAddIndication);
+ return 1;
+ }
+
+ /* Since it's not DSA_REQ, we can access all field in pstAddIndicationAlt */
+ /* We need to extract the structure from the buffer and pack it differently */
+
+ pstAddIndication->u8Type = pstAddIndicationAlt->u8Type;
+ pstAddIndication->eConnectionDir = pstAddIndicationAlt->u8Direction;
+ pstAddIndication->u16TID = pstAddIndicationAlt->u16TID;
+ pstAddIndication->u16CID = pstAddIndicationAlt->u16CID;
+ pstAddIndication->u16VCID = pstAddIndicationAlt->u16VCID;
+ pstAddIndication->u8CC = pstAddIndicationAlt->u8CC;
+
+ /* ADMITTED SET */
+ pstAddIndication->psfAdmittedSet = (struct bcm_connect_mgr_params *)
+ GetNextTargetBufferLocation(Adapter,
+ pstAddIndicationAlt->u16TID);
+ if (!pstAddIndication->psfAdmittedSet) {
+ kfree(pstAddIndication);
+ return 0;
+ }
+ if (StoreSFParam(Adapter, (PUCHAR)&pstAddIndicationAlt->sfAdmittedSet,
+ (ULONG)pstAddIndication->psfAdmittedSet) != 1) {
+ kfree(pstAddIndication);
+ return 0;
+ }
+
+ pstAddIndication->psfAdmittedSet =
+ (struct bcm_connect_mgr_params *) ntohl(
+ (ULONG) pstAddIndication->psfAdmittedSet);
+
+ /* ACTIVE SET */
+ pstAddIndication->psfActiveSet = (struct bcm_connect_mgr_params *)
+ GetNextTargetBufferLocation(Adapter,
+ pstAddIndicationAlt->u16TID);
+ if (!pstAddIndication->psfActiveSet) {
+ kfree(pstAddIndication);
+ return 0;
+ }
+ if (StoreSFParam(Adapter, (PUCHAR)&pstAddIndicationAlt->sfActiveSet,
+ (ULONG)pstAddIndication->psfActiveSet) != 1) {
+ kfree(pstAddIndication);
+ return 0;
+ }
+
+ pstAddIndication->psfActiveSet =
+ (struct bcm_connect_mgr_params *) ntohl(
+ (ULONG)pstAddIndication->psfActiveSet);
+
+ (*puBufferLength) = sizeof(struct bcm_add_indication);
+ *(struct bcm_add_indication *)pvBuffer = *pstAddIndication;
+ kfree(pstAddIndication);
+ return 1;
+}
+
+static inline struct bcm_add_indication_alt
+*RestoreCmControlResponseMessage(register struct bcm_mini_adapter *Adapter,
+ register PVOID pvBuffer)
+{
+ ULONG ulStatus = 0;
+ struct bcm_add_indication *pstAddIndication = NULL;
+ struct bcm_add_indication_alt *pstAddIndicationDest = NULL;
+
+ pstAddIndication = pvBuffer;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "=====>");
+ if ((pstAddIndication->u8Type == DSD_REQ) ||
+ (pstAddIndication->u8Type == DSD_RSP) ||
+ (pstAddIndication->u8Type == DSD_ACK))
+ return pvBuffer;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Inside RestoreCmControlResponseMessage ");
+ /*
+ * Need to Allocate memory to contain the SUPER Large structures
+ * Our driver can't create these structures on Stack :(
+ */
+ pstAddIndicationDest = kmalloc(sizeof(struct bcm_add_indication_alt),
+ GFP_KERNEL);
+
+ if (pstAddIndicationDest) {
+ memset(pstAddIndicationDest, 0,
+ sizeof(struct bcm_add_indication_alt));
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL,
+ "Failed to allocate memory for SF Add Indication Structure ");
+ return NULL;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-u8Type : 0x%X",
+ pstAddIndication->u8Type);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-u8Direction : 0x%X",
+ pstAddIndication->eConnectionDir);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-u8TID : 0x%X",
+ ntohs(pstAddIndication->u16TID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-u8CID : 0x%X",
+ ntohs(pstAddIndication->u16CID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-u16VCID : 0x%X",
+ ntohs(pstAddIndication->u16VCID));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-autorized set loc : %p",
+ pstAddIndication->psfAuthorizedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-admitted set loc : %p",
+ pstAddIndication->psfAdmittedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "AddIndication-Active set loc : %p",
+ pstAddIndication->psfActiveSet);
+
+ pstAddIndicationDest->u8Type = pstAddIndication->u8Type;
+ pstAddIndicationDest->u8Direction = pstAddIndication->eConnectionDir;
+ pstAddIndicationDest->u16TID = pstAddIndication->u16TID;
+ pstAddIndicationDest->u16CID = pstAddIndication->u16CID;
+ pstAddIndicationDest->u16VCID = pstAddIndication->u16VCID;
+ pstAddIndicationDest->u8CC = pstAddIndication->u8CC;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Restoring Active Set ");
+ ulStatus = RestoreSFParam(Adapter,
+ (ULONG)pstAddIndication->psfActiveSet,
+ (PUCHAR)&pstAddIndicationDest->sfActiveSet);
+ if (ulStatus != 1)
+ goto failed_restore_sf_param;
+
+ if (pstAddIndicationDest->sfActiveSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF)
+ pstAddIndicationDest->sfActiveSet.u8TotalClassifiers =
+ MAX_CLASSIFIERS_IN_SF;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Restoring Admitted Set ");
+ ulStatus = RestoreSFParam(Adapter,
+ (ULONG)pstAddIndication->psfAdmittedSet,
+ (PUCHAR)&pstAddIndicationDest->sfAdmittedSet);
+ if (ulStatus != 1)
+ goto failed_restore_sf_param;
+
+ if (pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF)
+ pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers =
+ MAX_CLASSIFIERS_IN_SF;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Restoring Authorized Set ");
+ ulStatus = RestoreSFParam(Adapter,
+ (ULONG)pstAddIndication->psfAuthorizedSet,
+ (PUCHAR)&pstAddIndicationDest->sfAuthorizedSet);
+ if (ulStatus != 1)
+ goto failed_restore_sf_param;
+
+ if (pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF)
+ pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers =
+ MAX_CLASSIFIERS_IN_SF;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Dumping the whole raw packet");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "============================================================");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ " pstAddIndicationDest->sfActiveSet size %zx %p",
+ sizeof(*pstAddIndicationDest), pstAddIndicationDest);
+ /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, CONN_MSG,
+ * DBG_LVL_ALL, (unsigned char *)pstAddIndicationDest,
+ * sizeof(*pstAddIndicationDest));
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "============================================================");
+ return pstAddIndicationDest;
+failed_restore_sf_param:
+ kfree(pstAddIndicationDest);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "<=====");
+ return NULL;
+}
+
+ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter)
+{
+ ULONG ulTargetDsxBuffersBase = 0;
+ ULONG ulCntTargetBuffers;
+ ULONG i;
+ int Status;
+
+ if (!Adapter) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Adapter was NULL!!!");
+ return 0;
+ }
+
+ if (Adapter->astTargetDsxBuffer[0].ulTargetDsxBuffer)
+ return 1;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Size of Each DSX Buffer(Also size of connection manager parameters): %zx ",
+ sizeof(struct bcm_connect_mgr_params));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Reading DSX buffer From Target location %x ",
+ DSX_MESSAGE_EXCHANGE_BUFFER);
+
+ Status = rdmalt(Adapter, DSX_MESSAGE_EXCHANGE_BUFFER,
+ (PUINT)&ulTargetDsxBuffersBase, sizeof(UINT));
+ if (Status < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "RDM failed!!");
+ return 0;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Base Address Of DSX Target Buffer : 0x%lx",
+ ulTargetDsxBuffersBase);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Tgt Buffer is Now %lx :", ulTargetDsxBuffersBase);
+ ulCntTargetBuffers = DSX_MESSAGE_EXCHANGE_BUFFER_SIZE /
+ sizeof(struct bcm_connect_mgr_params);
+
+ Adapter->ulTotalTargetBuffersAvailable =
+ ulCntTargetBuffers > MAX_TARGET_DSX_BUFFERS ?
+ MAX_TARGET_DSX_BUFFERS : ulCntTargetBuffers;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ " Total Target DSX Buffer setup %lx ",
+ Adapter->ulTotalTargetBuffersAvailable);
+
+ for (i = 0; i < Adapter->ulTotalTargetBuffersAvailable; i++) {
+ Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer = ulTargetDsxBuffersBase;
+ Adapter->astTargetDsxBuffer[i].valid = 1;
+ Adapter->astTargetDsxBuffer[i].tid = 0;
+ ulTargetDsxBuffersBase += sizeof(struct bcm_connect_mgr_params);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Target DSX Buffer %lx setup at 0x%lx",
+ i, Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer);
+ }
+ Adapter->ulCurrentTargetBuffer = 0;
+ Adapter->ulFreeTargetBufferCnt = Adapter->ulTotalTargetBuffersAvailable;
+ return 1;
+}
+
+static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter,
+ B_UINT16 tid)
+{
+ ULONG dsx_buf;
+ ULONG idx, max_try;
+
+ if ((Adapter->ulTotalTargetBuffersAvailable == 0)
+ || (Adapter->ulFreeTargetBufferCnt == 0)) {
+ ClearTargetDSXBuffer(Adapter, tid, false);
+ return 0;
+ }
+
+ idx = Adapter->ulCurrentTargetBuffer;
+ max_try = Adapter->ulTotalTargetBuffersAvailable;
+ while ((max_try) && (Adapter->astTargetDsxBuffer[idx].valid != 1)) {
+ idx = (idx+1) % Adapter->ulTotalTargetBuffersAvailable;
+ max_try--;
+ }
+
+ if (max_try == 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ",
+ Adapter->ulFreeTargetBufferCnt);
+ ClearTargetDSXBuffer(Adapter, tid, false);
+ return 0;
+ }
+
+ dsx_buf = Adapter->astTargetDsxBuffer[idx].ulTargetDsxBuffer;
+ Adapter->astTargetDsxBuffer[idx].valid = 0;
+ Adapter->astTargetDsxBuffer[idx].tid = tid;
+ Adapter->ulFreeTargetBufferCnt--;
+ idx = (idx+1)%Adapter->ulTotalTargetBuffersAvailable;
+ Adapter->ulCurrentTargetBuffer = idx;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "GetNextTargetBufferLocation :Returning address %lx tid %d\n",
+ dsx_buf, tid);
+
+ return dsx_buf;
+}
+
+int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter)
+{
+ /*
+ * Need to Allocate memory to contain the SUPER Large structures
+ * Our driver can't create these structures on Stack
+ */
+ Adapter->caDsxReqResp = kmalloc(sizeof(struct bcm_add_indication_alt)
+ + LEADER_SIZE, GFP_KERNEL);
+ if (!Adapter->caDsxReqResp)
+ return -ENOMEM;
+
+ return 0;
+}
+
+int FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter)
+{
+ kfree(Adapter->caDsxReqResp);
+ return 0;
+}
+
+/*
+ * @ingroup ctrl_pkt_functions
+ * This routinue would process the Control responses
+ * for the Connection Management.
+ * @return - Queue index for the free SFID else returns Invalid Index.
+ */
+bool CmControlResponseMessage(struct bcm_mini_adapter *Adapter, /* <Pointer to the Adapter structure */
+ PVOID pvBuffer /* Starting Address of the Buffer, that contains the AddIndication Data */)
+{
+ struct bcm_connect_mgr_params *psfLocalSet = NULL;
+ struct bcm_add_indication_alt *pstAddIndication = NULL;
+ struct bcm_change_indication *pstChangeIndication = NULL;
+ struct bcm_leader *pLeader = NULL;
+ INT uiSearchRuleIndex = 0;
+ ULONG ulSFID;
+
+ /*
+ * Otherwise the message contains a target address from where we need to
+ * read out the rest of the service flow param structure
+ */
+ pstAddIndication = RestoreCmControlResponseMessage(Adapter, pvBuffer);
+ if (pstAddIndication == NULL) {
+ ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication *)pvBuffer)->u16TID, false);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message");
+ return false;
+ }
+
+ DumpCmControlPacket(pstAddIndication);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "====>");
+ pLeader = (struct bcm_leader *)Adapter->caDsxReqResp;
+
+ pLeader->Status = CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ;
+ pLeader->Vcid = 0;
+
+ ClearTargetDSXBuffer(Adapter, pstAddIndication->u16TID, false);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "### TID RECEIVED %d\n", pstAddIndication->u16TID);
+ switch (pstAddIndication->u8Type) {
+ case DSA_REQ:
+ pLeader->PLength = sizeof(struct bcm_add_indication_alt);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Sending DSA Response....\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA RESPONSE TO MAC %d", pLeader->PLength);
+ *((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))
+ = *pstAddIndication;
+ ((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " VCID = %x", ntohs(pstAddIndication->u16VCID));
+ CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp);
+ kfree(pstAddIndication);
+ break;
+ case DSA_RSP:
+ pLeader->PLength = sizeof(struct bcm_add_indication_alt);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA ACK TO MAC %d",
+ pLeader->PLength);
+ *((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))
+ = *pstAddIndication;
+ ((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK;
+ /* FALLTHROUGH */
+ case DSA_ACK:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "VCID:0x%X",
+ ntohs(pstAddIndication->u16VCID));
+ uiSearchRuleIndex = SearchFreeSfid(Adapter);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "uiSearchRuleIndex:0x%X ",
+ uiSearchRuleIndex);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Direction:0x%X ",
+ pstAddIndication->u8Direction);
+ if (uiSearchRuleIndex < NO_OF_QUEUES) {
+ Adapter->PackInfo[uiSearchRuleIndex].ucDirection =
+ pstAddIndication->u8Direction;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "bValid:0x%X ",
+ pstAddIndication->sfActiveSet.bValid);
+ if (pstAddIndication->sfActiveSet.bValid == TRUE)
+ Adapter->PackInfo[uiSearchRuleIndex].bActiveSet = TRUE;
+
+ if (pstAddIndication->sfAuthorizedSet.bValid == TRUE)
+ Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet = TRUE;
+
+ if (pstAddIndication->sfAdmittedSet.bValid == TRUE)
+ Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE;
+
+ if (pstAddIndication->sfActiveSet.bValid == false) {
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+ Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = false;
+ if (pstAddIndication->sfAdmittedSet.bValid)
+ psfLocalSet = &pstAddIndication->sfAdmittedSet;
+ else if (pstAddIndication->sfAuthorizedSet.bValid)
+ psfLocalSet = &pstAddIndication->sfAuthorizedSet;
+ } else {
+ psfLocalSet = &pstAddIndication->sfActiveSet;
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = TRUE;
+ }
+
+ if (!psfLocalSet) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No set is valid\n");
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+ Adapter->PackInfo[uiSearchRuleIndex].bValid = false;
+ Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0;
+ kfree(pstAddIndication);
+ } else if (psfLocalSet->bValid && (pstAddIndication->u8CC == 0)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSA ACK");
+ Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pstAddIndication->u16VCID);
+ Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pstAddIndication->u16CID);
+
+ if (UPLINK_DIR == pstAddIndication->u8Direction)
+ atomic_set(&Adapter->PackInfo[uiSearchRuleIndex].uiPerSFTxResourceCount, DEFAULT_PERSFCOUNT);
+
+ CopyToAdapter(Adapter, psfLocalSet, uiSearchRuleIndex, DSA_ACK, pstAddIndication);
+ /* don't free pstAddIndication */
+
+ /* Inside CopyToAdapter, Sorting of all the SFs take place.
+ * Hence any access to the newly added SF through uiSearchRuleIndex is invalid.
+ * SHOULD BE STRICTLY AVOIDED.
+ */
+ /* *(PULONG)(((PUCHAR)pvBuffer)+1)=psfLocalSet->u32SFID; */
+ memcpy((((PUCHAR)pvBuffer)+1), &psfLocalSet->u32SFID, 4);
+
+ if (pstAddIndication->sfActiveSet.bValid == TRUE) {
+ if (UPLINK_DIR == pstAddIndication->u8Direction) {
+ if (!Adapter->LinkUpStatus) {
+ netif_carrier_on(Adapter->dev);
+ netif_start_queue(Adapter->dev);
+ Adapter->LinkUpStatus = 1;
+ if (netif_msg_link(Adapter))
+ pr_info(PFX "%s: link up\n", Adapter->dev->name);
+ atomic_set(&Adapter->TxPktAvail, 1);
+ wake_up(&Adapter->tx_packet_wait_queue);
+ Adapter->liTimeSinceLastNetEntry = get_seconds();
+ }
+ }
+ }
+ } else {
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+ Adapter->PackInfo[uiSearchRuleIndex].bValid = false;
+ Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0;
+ kfree(pstAddIndication);
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DSA ACK did not get valid SFID");
+ kfree(pstAddIndication);
+ return false;
+ }
+ break;
+ case DSC_REQ:
+ pLeader->PLength = sizeof(struct bcm_change_indication);
+ pstChangeIndication = (struct bcm_change_indication *)pstAddIndication;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC RESPONSE TO MAC %d", pLeader->PLength);
+
+ *((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication;
+ ((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP;
+
+ CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp);
+ kfree(pstAddIndication);
+ break;
+ case DSC_RSP:
+ pLeader->PLength = sizeof(struct bcm_change_indication);
+ pstChangeIndication = (struct bcm_change_indication *)pstAddIndication;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC ACK TO MAC %d", pLeader->PLength);
+ *((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication;
+ ((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK;
+ /* FALLTHROUGH */
+ case DSC_ACK:
+ pstChangeIndication = (struct bcm_change_indication *)pstAddIndication;
+ uiSearchRuleIndex = SearchSfid(Adapter, ntohl(pstChangeIndication->sfActiveSet.u32SFID));
+ if (uiSearchRuleIndex > NO_OF_QUEUES-1)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SF doesn't exist for which DSC_ACK is received");
+
+ if (uiSearchRuleIndex < NO_OF_QUEUES) {
+ Adapter->PackInfo[uiSearchRuleIndex].ucDirection = pstChangeIndication->u8Direction;
+ if (pstChangeIndication->sfActiveSet.bValid == TRUE)
+ Adapter->PackInfo[uiSearchRuleIndex].bActiveSet = TRUE;
+
+ if (pstChangeIndication->sfAuthorizedSet.bValid == TRUE)
+ Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet = TRUE;
+
+ if (pstChangeIndication->sfAdmittedSet.bValid == TRUE)
+ Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE;
+
+ if (pstChangeIndication->sfActiveSet.bValid == false) {
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+ Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = false;
+
+ if (pstChangeIndication->sfAdmittedSet.bValid)
+ psfLocalSet = &pstChangeIndication->sfAdmittedSet;
+ else if (pstChangeIndication->sfAuthorizedSet.bValid)
+ psfLocalSet = &pstChangeIndication->sfAuthorizedSet;
+ } else {
+ psfLocalSet = &pstChangeIndication->sfActiveSet;
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = TRUE;
+ }
+
+ if (!psfLocalSet) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No set is valid\n");
+ Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+ Adapter->PackInfo[uiSearchRuleIndex].bValid = false;
+ Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0;
+ kfree(pstAddIndication);
+ } else if (psfLocalSet->bValid && (pstChangeIndication->u8CC == 0)) {
+ Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pstChangeIndication->u16VCID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "CC field is %d bvalid = %d\n",
+ pstChangeIndication->u8CC, psfLocalSet->bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "VCID= %d\n", ntohs(pstChangeIndication->u16VCID));
+ Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pstChangeIndication->u16CID);
+ CopyToAdapter(Adapter, psfLocalSet, uiSearchRuleIndex, DSC_ACK, pstAddIndication);
+
+ *(PULONG)(((PUCHAR)pvBuffer)+1) = psfLocalSet->u32SFID;
+ } else if (pstChangeIndication->u8CC == 6) {
+ deleteSFBySfid(Adapter, uiSearchRuleIndex);
+ kfree(pstAddIndication);
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DSC ACK did not get valid SFID");
+ kfree(pstAddIndication);
+ return false;
+ }
+ break;
+ case DSD_REQ:
+ pLeader->PLength = sizeof(struct bcm_del_indication);
+ *((struct bcm_del_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *((struct bcm_del_indication *)pstAddIndication);
+
+ ulSFID = ntohl(((struct bcm_del_indication *)pstAddIndication)->u32SFID);
+ uiSearchRuleIndex = SearchSfid(Adapter, ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD - Removing connection %x", uiSearchRuleIndex);
+
+ if (uiSearchRuleIndex < NO_OF_QUEUES) {
+ /* Delete All Classifiers Associated with this SFID */
+ deleteSFBySfid(Adapter, uiSearchRuleIndex);
+ Adapter->u32TotalDSD++;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSD RESPONSE TO MAC");
+ ((struct bcm_del_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSD_RSP;
+ CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp);
+ /* FALLTHROUGH */
+ case DSD_RSP:
+ /* Do nothing as SF has already got Deleted */
+ break;
+ case DSD_ACK:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD ACK Rcd, let App handle it\n");
+ break;
+ default:
+ kfree(pstAddIndication);
+ return false;
+ }
+ return TRUE;
+}
+
+int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter,
+ UINT uiSFId, void __user *user_buffer)
+{
+ int status = 0;
+ struct bcm_packet_info *psSfInfo = NULL;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "status =%d", status);
+ status = SearchSfid(Adapter, uiSFId);
+ if (status >= NO_OF_QUEUES) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "SFID %d not present in queue !!!", uiSFId);
+ return -EINVAL;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "status =%d", status);
+ psSfInfo = &Adapter->PackInfo[status];
+ if (psSfInfo->pstSFIndication
+ && copy_to_user(user_buffer, psSfInfo->pstSFIndication,
+ sizeof(struct bcm_add_indication_alt))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "copy to user failed SFID %d, present in queue !!!",
+ uiSFId);
+ status = -EFAULT;
+ return status;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter,
+ PUINT puiBuffer)
+{
+ B_UINT32 u32NumofSFsinMsg = ntohl(*(puiBuffer + 1));
+ struct bcm_stim_sfhostnotify *pHostInfo = NULL;
+ UINT uiSearchRuleIndex = 0;
+ ULONG ulSFID = 0;
+
+ puiBuffer += 2;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "u32NumofSFsinMsg: 0x%x\n", u32NumofSFsinMsg);
+
+ while (u32NumofSFsinMsg != 0 && u32NumofSFsinMsg < NO_OF_QUEUES) {
+ u32NumofSFsinMsg--;
+ pHostInfo = (struct bcm_stim_sfhostnotify *)puiBuffer;
+ puiBuffer = (PUINT)(pHostInfo + 1);
+
+ ulSFID = ntohl(pHostInfo->SFID);
+ uiSearchRuleIndex = SearchSfid(Adapter, ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "SFID: 0x%lx\n", ulSFID);
+
+ if (uiSearchRuleIndex >= NO_OF_QUEUES
+ || uiSearchRuleIndex == HiPriority) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL,
+ "The SFID <%lx> doesn't exist in host entry or is Invalid\n",
+ ulSFID);
+ continue;
+ }
+
+ if (pHostInfo->RetainSF == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "Going to Delete SF");
+ deleteSFBySfid(Adapter, uiSearchRuleIndex);
+ } else {
+ struct bcm_packet_info *packinfo =
+ &Adapter->PackInfo[uiSearchRuleIndex];
+
+ packinfo->usVCID_Value = ntohs(pHostInfo->VCID);
+ packinfo->usCID = ntohs(pHostInfo->newCID);
+ packinfo->bActive = false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL,
+ "pHostInfo->QoSParamSet: 0x%x\n",
+ pHostInfo->QoSParamSet);
+
+ if (pHostInfo->QoSParamSet & 0x1)
+ packinfo->bAuthorizedSet = TRUE;
+ if (pHostInfo->QoSParamSet & 0x2)
+ packinfo->bAdmittedSet = TRUE;
+ if (pHostInfo->QoSParamSet & 0x4) {
+ packinfo->bActiveSet = TRUE;
+ packinfo->bActive = TRUE;
+ }
+ }
+ }
+}
+
+static void restore_endianess_of_pstClassifierEntry(
+ struct bcm_classifier_rule *pstClassifierEntry,
+ enum bcm_ipaddr_context eIpAddrContext)
+{
+ int i;
+ union u_ip_address *stSrc = &pstClassifierEntry->stSrcIpAddress;
+ union u_ip_address *stDest = &pstClassifierEntry->stDestIpAddress;
+
+ for (i = 0; i < MAX_IP_RANGE_LENGTH * 4; i++) {
+ if (eIpAddrContext == eSrcIpAddress) {
+ stSrc->ulIpv6Addr[i] = ntohl(stSrc->ulIpv6Addr[i]);
+ stSrc->ulIpv6Mask[i] = ntohl(stSrc->ulIpv6Mask[i]);
+ } else if (eIpAddrContext == eDestIpAddress) {
+ stDest->ulIpv6Addr[i] = ntohl(stDest->ulIpv6Addr[i]);
+ stDest->ulIpv6Mask[i] = ntohl(stDest->ulIpv6Mask[i]);
+ }
+ }
+}
+
+static void apply_phs_rule_to_all_classifiers(
+ register struct bcm_mini_adapter *Adapter, /* <Pointer to the Adapter structure */
+ register UINT uiSearchRuleIndex, /* <Index of Queue, to which this data belongs */
+ USHORT uVCID,
+ struct bcm_phs_rule *sPhsRule,
+ struct bcm_phs_rules *cPhsRule,
+ struct bcm_add_indication_alt *pstAddIndication)
+{
+ unsigned int uiClassifierIndex = 0;
+ struct bcm_classifier_rule *curr_classifier = NULL;
+
+ if (pstAddIndication->u8Direction == UPLINK_DIR) {
+ for (uiClassifierIndex = 0; uiClassifierIndex < MAX_CLASSIFIERS; uiClassifierIndex++) {
+ curr_classifier =
+ &Adapter->astClassifierTable[uiClassifierIndex];
+ if ((curr_classifier->bUsed) &&
+ (curr_classifier->ulSFID == Adapter->PackInfo[uiSearchRuleIndex].ulSFID) &&
+ (curr_classifier->u8AssociatedPHSI == cPhsRule->u8PHSI)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,
+ "Adding PHS Rule For Classifier: 0x%x cPhsRule.u8PHSI: 0x%x\n",
+ curr_classifier->uiClassifierRuleIndex,
+ cPhsRule->u8PHSI);
+ /* Update The PHS Rule for this classifier as Associated PHSI id defined */
+
+ /* Copy the PHS Rule */
+ sPhsRule->u8PHSI = cPhsRule->u8PHSI;
+ sPhsRule->u8PHSFLength = cPhsRule->u8PHSFLength;
+ sPhsRule->u8PHSMLength = cPhsRule->u8PHSMLength;
+ sPhsRule->u8PHSS = cPhsRule->u8PHSS;
+ sPhsRule->u8PHSV = cPhsRule->u8PHSV;
+ memcpy(sPhsRule->u8PHSF, cPhsRule->u8PHSF, MAX_PHS_LENGTHS);
+ memcpy(sPhsRule->u8PHSM, cPhsRule->u8PHSM, MAX_PHS_LENGTHS);
+ sPhsRule->u8RefCnt = 0;
+ sPhsRule->bUnclassifiedPHSRule = false;
+ sPhsRule->PHSModifiedBytes = 0;
+ sPhsRule->PHSModifiedNumPackets = 0;
+ sPhsRule->PHSErrorNumPackets = 0;
+
+ /* bPHSRuleAssociated = TRUE; */
+ /* Store The PHS Rule for this classifier */
+
+ PhsUpdateClassifierRule(
+ &Adapter->stBCMPhsContext,
+ uVCID,
+ curr_classifier->uiClassifierRuleIndex,
+ sPhsRule,
+ curr_classifier->u8AssociatedPHSI);
+
+ /* Update PHS Rule For the Classifier */
+ if (sPhsRule->u8PHSI) {
+ curr_classifier->u32PHSRuleID = sPhsRule->u8PHSI;
+ memcpy(&curr_classifier->sPhsRule, sPhsRule, sizeof(struct bcm_phs_rule));
+ }
+ }
+ }
+ } else {
+ /* Error PHS Rule specified in signaling could not be applied to any classifier */
+
+ /* Copy the PHS Rule */
+ sPhsRule->u8PHSI = cPhsRule->u8PHSI;
+ sPhsRule->u8PHSFLength = cPhsRule->u8PHSFLength;
+ sPhsRule->u8PHSMLength = cPhsRule->u8PHSMLength;
+ sPhsRule->u8PHSS = cPhsRule->u8PHSS;
+ sPhsRule->u8PHSV = cPhsRule->u8PHSV;
+ memcpy(sPhsRule->u8PHSF, cPhsRule->u8PHSF, MAX_PHS_LENGTHS);
+ memcpy(sPhsRule->u8PHSM, cPhsRule->u8PHSM, MAX_PHS_LENGTHS);
+ sPhsRule->u8RefCnt = 0;
+ sPhsRule->bUnclassifiedPHSRule = TRUE;
+ sPhsRule->PHSModifiedBytes = 0;
+ sPhsRule->PHSModifiedNumPackets = 0;
+ sPhsRule->PHSErrorNumPackets = 0;
+ /* Store The PHS Rule for this classifier */
+
+ /*
+ * Passing the argument u8PHSI instead of clsid. Because for DL with no classifier rule,
+ * clsid will be zero hence we can't have multiple PHS rules for the same SF.
+ * To support multiple PHS rule, passing u8PHSI.
+ */
+ PhsUpdateClassifierRule(
+ &Adapter->stBCMPhsContext,
+ uVCID,
+ sPhsRule->u8PHSI,
+ sPhsRule,
+ sPhsRule->u8PHSI);
+ }
+}
diff --git a/drivers/staging/bcm/CmHost.h b/drivers/staging/bcm/CmHost.h
new file mode 100644
index 00000000000..0887d3f49e2
--- /dev/null
+++ b/drivers/staging/bcm/CmHost.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * (c) Beceem Communications Inc.
+ * All Rights Reserved
+ *
+ * file : CmHost.h
+ * author: Rajeev Tirumala
+ * date : September 8 , 2006
+ * brief : Definitions for Connection Management Requests structure
+ * which we will use to setup our connection structures.Its high
+ * time we had a header file for CmHost.cpp to isolate the way
+ * f/w sends DSx messages and the way we interpret them in code.
+ * Revision History
+ *
+ * Date Author Version Description
+ * 08-Sep-06 Rajeev 0.1 Created
+ ***************************************************************************/
+#ifndef _CM_HOST_H
+#define _CM_HOST_H
+
+#pragma once
+#pragma pack(push, 4)
+
+#define DSX_MESSAGE_EXCHANGE_BUFFER 0xBF60AC84 /* This contains the pointer */
+#define DSX_MESSAGE_EXCHANGE_BUFFER_SIZE 72000 /* 24 K Bytes */
+
+struct bcm_add_indication_alt {
+ u8 u8Type;
+ u8 u8Direction;
+ u16 u16TID;
+ u16 u16CID;
+ u16 u16VCID;
+ struct bcm_connect_mgr_params sfAuthorizedSet;
+ struct bcm_connect_mgr_params sfAdmittedSet;
+ struct bcm_connect_mgr_params sfActiveSet;
+ u8 u8CC; /* < Confirmation Code */
+ u8 u8Padd;
+ u16 u16Padd;
+};
+
+struct bcm_change_indication {
+ u8 u8Type;
+ u8 u8Direction;
+ u16 u16TID;
+ u16 u16CID;
+ u16 u16VCID;
+ struct bcm_connect_mgr_params sfAuthorizedSet;
+ struct bcm_connect_mgr_params sfAdmittedSet;
+ struct bcm_connect_mgr_params sfActiveSet;
+ u8 u8CC; /* < Confirmation Code */
+ u8 u8Padd;
+ u16 u16Padd;
+};
+
+unsigned long StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer, unsigned int *puBufferLength);
+int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
+int FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
+unsigned long SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter);
+bool CmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer);
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c
new file mode 100644
index 00000000000..f1d7cb82fd7
--- /dev/null
+++ b/drivers/staging/bcm/DDRInit.c
@@ -0,0 +1,1239 @@
+#include "headers.h"
+
+
+
+#define DDR_DUMP_INTERNAL_DEVICE_MEMORY 0xBFC02B00
+#define MIPS_CLOCK_REG 0x0f000820
+
+/* DDR INIT-133Mhz */
+#define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3_DDRSetting133MHz[] = { /* DPLL Clock Setting */
+ {0x0F000800, 0x00007212},
+ {0x0f000820, 0x07F13FFF},
+ {0x0f000810, 0x00000F95},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF1B00},
+ {0x0f000870, 0x00000002},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ {0x0F00a04C, 0x0000000C},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020001},
+ {0x0F007020, 0x04030107},
+ {0x0F007024, 0x02000007},
+ {0x0F007028, 0x02020202},
+ {0x0F00702c, 0x0206060a},
+ {0x0F007030, 0x05000000},
+ {0x0F007034, 0x00000003},
+ {0x0F007038, 0x110a0200},
+ {0x0F00703C, 0x02101010},
+ {0x0F007040, 0x45751200},
+ {0x0F007044, 0x110a0d00},
+ {0x0F007048, 0x081b0306},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0000001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x0010246c},
+ {0x0F007064, 0x00000010},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00007000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ /* Enable BW improvement within memory controller */
+ {0x0F007094, 0x00000104},
+ /* Enable 2 ports within X-bar */
+ {0x0F00A000, 0x00000016},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+/* 80Mhz */
+#define T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 10 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3_DDRSetting80MHz[] = { /* DPLL Clock Setting */
+ {0x0f000810, 0x00000F95},
+ {0x0f000820, 0x07f1ffff},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ {0x0F00a000, 0x00000016},
+ {0x0F00a04C, 0x0000000C},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01000000},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020000},
+ {0x0F007020, 0x04020107},
+ {0x0F007024, 0x00000007},
+ {0x0F007028, 0x02020201},
+ {0x0F00702c, 0x0204040a},
+ {0x0F007030, 0x04000000},
+ {0x0F007034, 0x00000002},
+ {0x0F007038, 0x1F060200},
+ {0x0F00703C, 0x1C22221F},
+ {0x0F007040, 0x8A006600},
+ {0x0F007044, 0x221a0800},
+ {0x0F007048, 0x02690204},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0000001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x000A15D6},
+ {0x0F007064, 0x0000000A},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00004000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ {0x0F007094, 0x00000104},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+/* 100Mhz */
+#define T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 13 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3_DDRSetting100MHz[] = { /* DPLL Clock Setting */
+ {0x0F000800, 0x00007008},
+ {0x0f000810, 0x00000F95},
+ {0x0f000820, 0x07F13E3F},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF1B00},
+ {0x0f000870, 0x00000002},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ {0x0F00a04C, 0x0000000C},
+ /* Enable 2 ports within X-bar */
+ {0x0F00A000, 0x00000016},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020001},
+ {0x0F007020, 0x04020107},
+ {0x0F007024, 0x00000007},
+ {0x0F007028, 0x01020201},
+ {0x0F00702c, 0x0204040A},
+ {0x0F007030, 0x06000000},
+ {0x0F007034, 0x00000004},
+ {0x0F007038, 0x20080200},
+ {0x0F00703C, 0x02030320},
+ {0x0F007040, 0x6E7F1200},
+ {0x0F007044, 0x01190A00},
+ {0x0F007048, 0x06120305},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0000001C},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x00082ED6},
+ {0x0F007064, 0x0000000A},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00005000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ /* Enable BW improvement within memory controller */
+ {0x0F007094, 0x00000104},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+/* Net T3B DDR Settings
+ * DDR INIT-133Mhz
+ */
+static struct bcm_ddr_setting asDPLL_266MHZ[] = {
+ {0x0F000800, 0x00007212},
+ {0x0f000820, 0x07F13FFF},
+ {0x0f000810, 0x00000F95},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF1B00},
+ {0x0f000870, 0x00000002}
+};
+
+#define T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 11 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3B_DDRSetting133MHz[] = { /* DPLL Clock Setting */
+ {0x0f000810, 0x00000F95},
+ {0x0f000810, 0x00000F95},
+ {0x0f000810, 0x00000F95},
+ {0x0f000820, 0x07F13652},
+ {0x0f000840, 0x0FFF0800},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000880, 0x000003DD},
+ {0x0f000860, 0x00000000},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ /* Enable 2 ports within X-bar */
+ {0x0F00A000, 0x00000016},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020001},
+ {0x0F007020, 0x04030107},
+ {0x0F007024, 0x02000007},
+ {0x0F007028, 0x02020202},
+ {0x0F00702c, 0x0206060a},
+ {0x0F007030, 0x05000000},
+ {0x0F007034, 0x00000003},
+ {0x0F007038, 0x130a0200},
+ {0x0F00703C, 0x02101012},
+ {0x0F007040, 0x457D1200},
+ {0x0F007044, 0x11130d00},
+ {0x0F007048, 0x040D0306},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0000001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x0010246c},
+ {0x0F007064, 0x00000012},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00007000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ /* Enable BW improvement within memory controller */
+ {0x0F007094, 0x00000104},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000},
+ };
+
+#define T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3B_DDRSetting80MHz[] = { /* DPLL Clock Setting */
+ {0x0f000810, 0x00000F95},
+ {0x0f000820, 0x07F13FFF},
+ {0x0f000840, 0x0FFF1F00},
+ {0x0f000880, 0x000003DD},
+ {0x0f000860, 0x00000000},
+
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ {0x0F00a000, 0x00000016},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01000000},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020000},
+ {0x0F007020, 0x04020107},
+ {0x0F007024, 0x00000007},
+ {0x0F007028, 0x02020201},
+ {0x0F00702c, 0x0204040a},
+ {0x0F007030, 0x04000000},
+ {0x0F007034, 0x02000002},
+ {0x0F007038, 0x1F060202},
+ {0x0F00703C, 0x1C22221F},
+ {0x0F007040, 0x8A006600},
+ {0x0F007044, 0x221a0800},
+ {0x0F007048, 0x02690204},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0100001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x000A15D6},
+ {0x0F007064, 0x0000000A},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00004000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ {0x0F007094, 0x00000104},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+/* 100Mhz */
+#define T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 9 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3B_DDRSetting100MHz[] = { /* DPLL Clock Setting */
+ {0x0f000810, 0x00000F95},
+ {0x0f000820, 0x07F1369B},
+ {0x0f000840, 0x0FFF0800},
+ {0x0f000880, 0x000003DD},
+ {0x0f000860, 0x00000000},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ /* Enable 2 ports within X-bar */
+ {0x0F00A000, 0x00000016},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020000},
+ {0x0F007020, 0x04020107},
+ {0x0F007024, 0x00000007},
+ {0x0F007028, 0x01020201},
+ {0x0F00702c, 0x0204040A},
+ {0x0F007030, 0x06000000},
+ {0x0F007034, 0x02000004},
+ {0x0F007038, 0x20080200},
+ {0x0F00703C, 0x02030320},
+ {0x0F007040, 0x6E7F1200},
+ {0x0F007044, 0x01190A00},
+ {0x0F007048, 0x06120305},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0100001C},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x00082ED6},
+ {0x0F007064, 0x0000000A},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00005000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ /* Enable BW improvement within memory controller */
+ {0x0F007094, 0x00000104},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+
+#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 9 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LP_DDRSetting133MHz[] = { /* DPLL Clock Setting */
+ {0x0f000820, 0x03F1365B},
+ {0x0f000810, 0x00002F95},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF0000},
+ {0x0f000860, 0x00000000},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ {0x0F00A000, 0x00000016},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020001},
+ {0x0F007020, 0x04030107},
+ {0x0F007024, 0x02000007},
+ {0x0F007028, 0x02020200},
+ {0x0F00702c, 0x0206060a},
+ {0x0F007030, 0x05000000},
+ {0x0F007034, 0x00000003},
+ {0x0F007038, 0x200a0200},
+ {0x0F00703C, 0x02101020},
+ {0x0F007040, 0x45711200},
+ {0x0F007044, 0x110D0D00},
+ {0x0F007048, 0x04080306},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0100001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x0010245F},
+ {0x0F007064, 0x00000010},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00007000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ {0x0F007088, 0x01000001},
+ {0x0F00708c, 0x00000101},
+ {0x0F007090, 0x00000000},
+ /* Enable BW improvement within memory controller */
+ {0x0F007094, 0x00040000},
+ {0x0F007098, 0x00000000},
+ {0x0F0070c8, 0x00000104},
+ /* Enable 2 ports within X-bar */
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 11 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LP_DDRSetting100MHz[] = { /* DPLL Clock Setting */
+ {0x0f000810, 0x00002F95},
+ {0x0f000820, 0x03F1369B},
+ {0x0f000840, 0x0fff0000},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF0000},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020000},
+ {0x0F007020, 0x04020107},
+ {0x0F007024, 0x00000007},
+ {0x0F007028, 0x01020200},
+ {0x0F00702c, 0x0204040a},
+ {0x0F007030, 0x06000000},
+ {0x0F007034, 0x00000004},
+ {0x0F007038, 0x1F080200},
+ {0x0F00703C, 0x0203031F},
+ {0x0F007040, 0x6e001200},
+ {0x0F007044, 0x011a0a00},
+ {0x0F007048, 0x03000305},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0100001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x00082ED6},
+ {0x0F007064, 0x0000000A},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00005000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ {0x0F007088, 0x01000001},
+ {0x0F00708c, 0x00000101},
+ {0x0F007090, 0x00000000},
+ {0x0F007094, 0x00010000},
+ {0x0F007098, 0x00000000},
+ {0x0F0070C8, 0x00000104},
+ /* Enable 2 ports within X-bar */
+ {0x0F00A000, 0x00000016},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[] = { /* DPLL Clock Setting */
+ {0x0f000820, 0x07F13FFF},
+ {0x0f000810, 0x00002F95},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ {0x0f000840, 0x0FFF1F00},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0F00a084, 0x1Cffffff},
+ {0x0F00a080, 0x1C000000},
+ {0x0F00A000, 0x00000016},
+ {0x0f007000, 0x00010001},
+ {0x0f007004, 0x01000000},
+ {0x0f007008, 0x01000001},
+ {0x0f00700c, 0x00000000},
+ {0x0f007010, 0x01000000},
+ {0x0f007014, 0x01000100},
+ {0x0f007018, 0x01000000},
+ {0x0f00701c, 0x01020000},
+ {0x0f007020, 0x04020107},
+ {0x0f007024, 0x00000007},
+ {0x0f007028, 0x02020200},
+ {0x0f00702c, 0x0204040a},
+ {0x0f007030, 0x04000000},
+ {0x0f007034, 0x00000002},
+ {0x0f007038, 0x1d060200},
+ {0x0f00703c, 0x1c22221d},
+ {0x0f007040, 0x8A116600},
+ {0x0f007044, 0x222d0800},
+ {0x0f007048, 0x02690204},
+ {0x0f00704c, 0x00000000},
+ {0x0f007050, 0x0100001c},
+ {0x0f007054, 0x00000000},
+ {0x0f007058, 0x00000000},
+ {0x0f00705c, 0x00000000},
+ {0x0f007060, 0x000A15D6},
+ {0x0f007064, 0x0000000A},
+ {0x0f007068, 0x00000000},
+ {0x0f00706c, 0x00000001},
+ {0x0f007070, 0x00004000},
+ {0x0f007074, 0x00000000},
+ {0x0f007078, 0x00000000},
+ {0x0f00707c, 0x00000000},
+ {0x0f007080, 0x00000000},
+ {0x0f007084, 0x00000000},
+ {0x0f007088, 0x01000001},
+ {0x0f00708c, 0x00000101},
+ {0x0f007090, 0x00000000},
+ {0x0f007094, 0x00010000},
+ {0x0f007098, 0x00000000},
+ {0x0F0070C8, 0x00000104},
+ {0x0F007018, 0x01010000}
+};
+
+
+
+
+/* T3 LP-B (UMA-B) */
+
+#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ 7 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LPB_DDRSetting160MHz[] = { /* DPLL Clock Setting */
+ {0x0f000820, 0x03F137DB},
+ {0x0f000810, 0x01842795},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ {0x0f000840, 0x0FFF0400},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0f003050, 0x00000021}, /* this is flash/eeprom clock divisor which set the flash clock to 20 MHz */
+ {0x0F00a084, 0x1Cffffff}, /* Now dump from her in internal memory */
+ {0x0F00a080, 0x1C000000},
+ {0x0F00A000, 0x00000016},
+ {0x0f007000, 0x00010001},
+ {0x0f007004, 0x01000001},
+ {0x0f007008, 0x01000101},
+ {0x0f00700c, 0x00000000},
+ {0x0f007010, 0x01000100},
+ {0x0f007014, 0x01000100},
+ {0x0f007018, 0x01000000},
+ {0x0f00701c, 0x01020000},
+ {0x0f007020, 0x04030107},
+ {0x0f007024, 0x02000007},
+ {0x0f007028, 0x02020200},
+ {0x0f00702c, 0x0206060a},
+ {0x0f007030, 0x050d0d00},
+ {0x0f007034, 0x00000003},
+ {0x0f007038, 0x170a0200},
+ {0x0f00703c, 0x02101012},
+ {0x0f007040, 0x45161200},
+ {0x0f007044, 0x11250c00},
+ {0x0f007048, 0x04da0307},
+ {0x0f00704c, 0x00000000},
+ {0x0f007050, 0x0000001c},
+ {0x0f007054, 0x00000000},
+ {0x0f007058, 0x00000000},
+ {0x0f00705c, 0x00000000},
+ {0x0f007060, 0x00142bb6},
+ {0x0f007064, 0x20430014},
+ {0x0f007068, 0x00000000},
+ {0x0f00706c, 0x00000001},
+ {0x0f007070, 0x00009000},
+ {0x0f007074, 0x00000000},
+ {0x0f007078, 0x00000000},
+ {0x0f00707c, 0x00000000},
+ {0x0f007080, 0x00000000},
+ {0x0f007084, 0x00000000},
+ {0x0f007088, 0x01000001},
+ {0x0f00708c, 0x00000101},
+ {0x0f007090, 0x00000000},
+ {0x0f007094, 0x00040000},
+ {0x0f007098, 0x00000000},
+ {0x0F0070C8, 0x00000104},
+ {0x0F007018, 0x01010000}
+};
+
+
+#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 7 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LPB_DDRSetting133MHz[] = { /* DPLL Clock Setting */
+ {0x0f000820, 0x03F1365B},
+ {0x0f000810, 0x00002F95},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF0000},
+ {0x0f000860, 0x00000000},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0f003050, 0x00000021}, /* flash/eeprom clock divisor which set the flash clock to 20 MHz */
+ {0x0F00a084, 0x1Cffffff}, /* dump from here in internal memory */
+ {0x0F00a080, 0x1C000000},
+ {0x0F00A000, 0x00000016},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020001},
+ {0x0F007020, 0x04030107},
+ {0x0F007024, 0x02000007},
+ {0x0F007028, 0x02020200},
+ {0x0F00702c, 0x0206060a},
+ {0x0F007030, 0x05000000},
+ {0x0F007034, 0x00000003},
+ {0x0F007038, 0x190a0200},
+ {0x0F00703C, 0x02101017},
+ {0x0F007040, 0x45171200},
+ {0x0F007044, 0x11290D00},
+ {0x0F007048, 0x04080306},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0100001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x0010245F},
+ {0x0F007064, 0x00000010},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00007000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ {0x0F007088, 0x01000001},
+ {0x0F00708c, 0x00000101},
+ {0x0F007090, 0x00000000},
+ /* Enable BW improvement within memory controller */
+ {0x0F007094, 0x00040000},
+ {0x0F007098, 0x00000000},
+ {0x0F0070c8, 0x00000104},
+ /* Enable 2 ports within X-bar */
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 8 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LPB_DDRSetting100MHz[] = { /* DPLL Clock Setting */
+ {0x0f000810, 0x00002F95},
+ {0x0f000820, 0x03F1369B},
+ {0x0f000840, 0x0fff0000},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ /* Changed source for X-bar and MIPS clock to APLL */
+ {0x0f000840, 0x0FFF0000},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0f003050, 0x00000021}, /* flash/eeprom clock divisor which set the flash clock to 20 MHz */
+ {0x0F00a084, 0x1Cffffff}, /* dump from here in internal memory */
+ {0x0F00a080, 0x1C000000},
+ /* Memcontroller Default values */
+ {0x0F007000, 0x00010001},
+ {0x0F007004, 0x01010100},
+ {0x0F007008, 0x01000001},
+ {0x0F00700c, 0x00000000},
+ {0x0F007010, 0x01000000},
+ {0x0F007014, 0x01000100},
+ {0x0F007018, 0x01000000},
+ {0x0F00701c, 0x01020000},
+ {0x0F007020, 0x04020107},
+ {0x0F007024, 0x00000007},
+ {0x0F007028, 0x01020200},
+ {0x0F00702c, 0x0204040a},
+ {0x0F007030, 0x06000000},
+ {0x0F007034, 0x00000004},
+ {0x0F007038, 0x1F080200},
+ {0x0F00703C, 0x0203031F},
+ {0x0F007040, 0x6e001200},
+ {0x0F007044, 0x011a0a00},
+ {0x0F007048, 0x03000305},
+ {0x0F00704c, 0x00000000},
+ {0x0F007050, 0x0100001c},
+ {0x0F007054, 0x00000000},
+ {0x0F007058, 0x00000000},
+ {0x0F00705c, 0x00000000},
+ {0x0F007060, 0x00082ED6},
+ {0x0F007064, 0x0000000A},
+ {0x0F007068, 0x00000000},
+ {0x0F00706c, 0x00000001},
+ {0x0F007070, 0x00005000},
+ {0x0F007074, 0x00000000},
+ {0x0F007078, 0x00000000},
+ {0x0F00707C, 0x00000000},
+ {0x0F007080, 0x00000000},
+ {0x0F007084, 0x00000000},
+ {0x0F007088, 0x01000001},
+ {0x0F00708c, 0x00000101},
+ {0x0F007090, 0x00000000},
+ {0x0F007094, 0x00010000},
+ {0x0F007098, 0x00000000},
+ {0x0F0070C8, 0x00000104},
+ /* Enable 2 ports within X-bar */
+ {0x0F00A000, 0x00000016},
+ /* Enable start bit within memory controller */
+ {0x0F007018, 0x01010000}
+};
+
+#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 7 /* index for 0x0F007000 */
+static struct bcm_ddr_setting asT3LPB_DDRSetting80MHz[] = { /* DPLL Clock Setting */
+ {0x0f000820, 0x07F13FFF},
+ {0x0f000810, 0x00002F95},
+ {0x0f000860, 0x00000000},
+ {0x0f000880, 0x000003DD},
+ {0x0f000840, 0x0FFF1F00},
+ {0x0F00a044, 0x1fffffff},
+ {0x0F00a040, 0x1f000000},
+ {0x0f003050, 0x00000021}, /* flash/eeprom clock divisor which set the flash clock to 20 MHz */
+ {0x0F00a084, 0x1Cffffff}, /* dump from here in internal memory */
+ {0x0F00a080, 0x1C000000},
+ {0x0F00A000, 0x00000016},
+ {0x0f007000, 0x00010001},
+ {0x0f007004, 0x01000000},
+ {0x0f007008, 0x01000001},
+ {0x0f00700c, 0x00000000},
+ {0x0f007010, 0x01000000},
+ {0x0f007014, 0x01000100},
+ {0x0f007018, 0x01000000},
+ {0x0f00701c, 0x01020000},
+ {0x0f007020, 0x04020107},
+ {0x0f007024, 0x00000007},
+ {0x0f007028, 0x02020200},
+ {0x0f00702c, 0x0204040a},
+ {0x0f007030, 0x04000000},
+ {0x0f007034, 0x00000002},
+ {0x0f007038, 0x1d060200},
+ {0x0f00703c, 0x1c22221d},
+ {0x0f007040, 0x8A116600},
+ {0x0f007044, 0x222d0800},
+ {0x0f007048, 0x02690204},
+ {0x0f00704c, 0x00000000},
+ {0x0f007050, 0x0100001c},
+ {0x0f007054, 0x00000000},
+ {0x0f007058, 0x00000000},
+ {0x0f00705c, 0x00000000},
+ {0x0f007060, 0x000A15D6},
+ {0x0f007064, 0x0000000A},
+ {0x0f007068, 0x00000000},
+ {0x0f00706c, 0x00000001},
+ {0x0f007070, 0x00004000},
+ {0x0f007074, 0x00000000},
+ {0x0f007078, 0x00000000},
+ {0x0f00707c, 0x00000000},
+ {0x0f007080, 0x00000000},
+ {0x0f007084, 0x00000000},
+ {0x0f007088, 0x01000001},
+ {0x0f00708c, 0x00000101},
+ {0x0f007090, 0x00000000},
+ {0x0f007094, 0x00010000},
+ {0x0f007098, 0x00000000},
+ {0x0F0070C8, 0x00000104},
+ {0x0F007018, 0x01010000}
+};
+
+
+int ddr_init(struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ddr_setting *psDDRSetting = NULL;
+ ULONG RegCount = 0;
+ UINT value = 0;
+ UINT uiResetValue = 0;
+ UINT uiClockSetting = 0;
+ int retval = STATUS_SUCCESS;
+
+ switch (Adapter->chip_id) {
+ case 0xbece3200:
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3LP_DDRSetting80MHz;
+ RegCount = (sizeof(asT3LP_DDRSetting80MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3LP_DDRSetting100MHz;
+ RegCount = (sizeof(asT3LP_DDRSetting100MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_133_MHZ:
+ psDDRSetting = asT3LP_DDRSetting133MHz;
+ RegCount = (sizeof(asT3LP_DDRSetting133MHz)/
+ sizeof(struct bcm_ddr_setting));
+ if (Adapter->bMipsConfig == MIPS_200_MHZ)
+ uiClockSetting = 0x03F13652;
+ else
+ uiClockSetting = 0x03F1365B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ break;
+ case T3LPB:
+ case BCS220_2:
+ case BCS220_2BC:
+ case BCS250_BC:
+ case BCS220_3:
+ /* Set bit 2 and bit 6 to 1 for BBIC 2mA drive
+ * (please check current value and additionally set these bits)
+ */
+ if ((Adapter->chip_id != BCS220_2) &&
+ (Adapter->chip_id != BCS220_2BC) &&
+ (Adapter->chip_id != BCS220_3)) {
+ retval = rdmalt(Adapter, (UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue |= 0x44;
+ retval = wrmalt(Adapter, (UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ }
+ switch (Adapter->DDRSetting) {
+
+
+
+ case DDR_80_MHZ:
+ psDDRSetting = asT3LPB_DDRSetting80MHz;
+ RegCount = (sizeof(asT3B_DDRSetting80MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3LPB_DDRSetting100MHz;
+ RegCount = (sizeof(asT3B_DDRSetting100MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_133_MHZ:
+ psDDRSetting = asT3LPB_DDRSetting133MHz;
+ RegCount = (sizeof(asT3B_DDRSetting133MHz)/
+ sizeof(struct bcm_ddr_setting));
+
+ if (Adapter->bMipsConfig == MIPS_200_MHZ)
+ uiClockSetting = 0x03F13652;
+ else
+ uiClockSetting = 0x03F1365B;
+ break;
+
+ case DDR_160_MHZ:
+ psDDRSetting = asT3LPB_DDRSetting160MHz;
+ RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(struct bcm_ddr_setting);
+
+ if (Adapter->bMipsConfig == MIPS_200_MHZ)
+ uiClockSetting = 0x03F137D2;
+ else
+ uiClockSetting = 0x03F137DB;
+ }
+ break;
+
+ case 0xbece0110:
+ case 0xbece0120:
+ case 0xbece0121:
+ case 0xbece0130:
+ case 0xbece0300:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting);
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3_DDRSetting80MHz;
+ RegCount = (sizeof(asT3_DDRSetting80MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3_DDRSetting100MHz;
+ RegCount = (sizeof(asT3_DDRSetting100MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_133_MHZ:
+ psDDRSetting = asT3_DDRSetting133MHz;
+ RegCount = (sizeof(asT3_DDRSetting133MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ default:
+ return -EINVAL;
+ }
+ case 0xbece0310:
+ {
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3B_DDRSetting80MHz;
+ RegCount = (sizeof(asT3B_DDRSetting80MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3B_DDRSetting100MHz;
+ RegCount = (sizeof(asT3B_DDRSetting100MHz)/
+ sizeof(struct bcm_ddr_setting));
+ break;
+ case DDR_133_MHZ:
+
+ if (Adapter->bDPLLConfig == PLL_266_MHZ) { /* 266Mhz PLL selected. */
+ memcpy(asT3B_DDRSetting133MHz, asDPLL_266MHZ,
+ sizeof(asDPLL_266MHZ));
+ psDDRSetting = asT3B_DDRSetting133MHz;
+ RegCount = (sizeof(asT3B_DDRSetting133MHz)/
+ sizeof(struct bcm_ddr_setting));
+ } else {
+ psDDRSetting = asT3B_DDRSetting133MHz;
+ RegCount = (sizeof(asT3B_DDRSetting133MHz)/
+ sizeof(struct bcm_ddr_setting));
+ if (Adapter->bMipsConfig == MIPS_200_MHZ)
+ uiClockSetting = 0x07F13652;
+ else
+ uiClockSetting = 0x07F1365B;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ }
+ default:
+ return -EINVAL;
+ }
+
+ value = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register Count is =%lu\n", RegCount);
+ while (RegCount && !retval) {
+ if (uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG)
+ value = uiClockSetting;
+ else
+ value = psDDRSetting->ulRegValue;
+ retval = wrmalt(Adapter, psDDRSetting->ulRegAddress, &value, sizeof(value));
+ if (STATUS_SUCCESS != retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+ break;
+ }
+
+ RegCount--;
+ psDDRSetting++;
+ }
+
+ if (Adapter->chip_id >= 0xbece3300) {
+
+ mdelay(3);
+ if ((Adapter->chip_id != BCS220_2) &&
+ (Adapter->chip_id != BCS220_2BC) &&
+ (Adapter->chip_id != BCS220_3)) {
+ /* drive MDDR to half in case of UMA-B: */
+ uiResetValue = 0x01010001;
+ retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x00040020;
+ retval = wrmalt(Adapter, (UINT)0x0F007094, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x01020101;
+ retval = wrmalt(Adapter, (UINT)0x0F00701c, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x01010000;
+ retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ }
+ mdelay(3);
+
+ /* DC/DC standby change...
+ * This is to be done only for Hybrid PMU mode.
+ * with the current h/w there is no way to detect this.
+ * and since we dont have internal PMU lets do it under UMA-B chip id.
+ * we will change this when we will have internal PMU.
+ */
+ if (Adapter->PmuMode == HYBRID_MODE_7C) {
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x1322a8;
+ retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x132296;
+ retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ } else if (Adapter->PmuMode == HYBRID_MODE_6) {
+
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x6003229a;
+ retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ retval = rdmalt(Adapter, (UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ uiResetValue = 0x1322a8;
+ retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__);
+ return retval;
+ }
+ }
+
+ }
+ Adapter->bDDRInitDone = TRUE;
+ return retval;
+}
+
+int download_ddr_settings(struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_ddr_setting *psDDRSetting = NULL;
+ ULONG RegCount = 0;
+ unsigned long ul_ddr_setting_load_addr = DDR_DUMP_INTERNAL_DEVICE_MEMORY;
+ UINT value = 0;
+ int retval = STATUS_SUCCESS;
+ bool bOverrideSelfRefresh = false;
+
+ switch (Adapter->chip_id) {
+ case 0xbece3200:
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3LP_DDRSetting80MHz;
+ RegCount = ARRAY_SIZE(asT3LP_DDRSetting80MHz);
+ RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3LP_DDRSetting100MHz;
+ RegCount = ARRAY_SIZE(asT3LP_DDRSetting100MHz);
+ RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ break;
+ case DDR_133_MHZ:
+ bOverrideSelfRefresh = TRUE;
+ psDDRSetting = asT3LP_DDRSetting133MHz;
+ RegCount = ARRAY_SIZE(asT3LP_DDRSetting133MHz);
+ RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case T3LPB:
+ case BCS220_2:
+ case BCS220_2BC:
+ case BCS250_BC:
+ case BCS220_3:
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3LPB_DDRSetting80MHz;
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting80MHz);
+ RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3LPB_DDRSetting100MHz;
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting100MHz);
+ RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ break;
+ case DDR_133_MHZ:
+ bOverrideSelfRefresh = TRUE;
+ psDDRSetting = asT3LPB_DDRSetting133MHz;
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting133MHz);
+ RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ break;
+
+ case DDR_160_MHZ:
+ bOverrideSelfRefresh = TRUE;
+ psDDRSetting = asT3LPB_DDRSetting160MHz;
+ RegCount = ARRAY_SIZE(asT3LPB_DDRSetting160MHz);
+ RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
+ psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case 0xbece0300:
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3_DDRSetting80MHz;
+ RegCount = ARRAY_SIZE(asT3_DDRSetting80MHz);
+ RegCount -= T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3_DDRSetting100MHz;
+ RegCount = ARRAY_SIZE(asT3_DDRSetting100MHz);
+ RegCount -= T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ break;
+ case DDR_133_MHZ:
+ psDDRSetting = asT3_DDRSetting133MHz;
+ RegCount = ARRAY_SIZE(asT3_DDRSetting133MHz);
+ RegCount -= T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case 0xbece0310:
+ {
+ switch (Adapter->DDRSetting) {
+ case DDR_80_MHZ:
+ psDDRSetting = asT3B_DDRSetting80MHz;
+ RegCount = ARRAY_SIZE(asT3B_DDRSetting80MHz);
+ RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
+ break;
+ case DDR_100_MHZ:
+ psDDRSetting = asT3B_DDRSetting100MHz;
+ RegCount = ARRAY_SIZE(asT3B_DDRSetting100MHz);
+ RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
+ break;
+ case DDR_133_MHZ:
+ bOverrideSelfRefresh = TRUE;
+ psDDRSetting = asT3B_DDRSetting133MHz;
+ RegCount = ARRAY_SIZE(asT3B_DDRSetting133MHz);
+ RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
+ break;
+ }
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ /* total number of Register that has to be dumped */
+ value = RegCount;
+ retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value));
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+
+ return retval;
+ }
+ ul_ddr_setting_load_addr += sizeof(ULONG);
+ /* signature */
+ value = (0x1d1e0dd0);
+ retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value));
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+ return retval;
+ }
+
+ ul_ddr_setting_load_addr += sizeof(ULONG);
+ RegCount *= (sizeof(struct bcm_ddr_setting)/sizeof(ULONG));
+
+ while (RegCount && !retval) {
+ value = psDDRSetting->ulRegAddress;
+ retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value));
+ ul_ddr_setting_load_addr += sizeof(ULONG);
+ if (!retval) {
+ if (bOverrideSelfRefresh && (psDDRSetting->ulRegAddress == 0x0F007018)) {
+ value = (psDDRSetting->ulRegValue | (1<<8));
+ if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr,
+ &value, sizeof(value))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+ break;
+ }
+ } else {
+ value = psDDRSetting->ulRegValue;
+
+ if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr ,
+ &value, sizeof(value))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__);
+ break;
+ }
+ }
+ }
+ ul_ddr_setting_load_addr += sizeof(ULONG);
+ RegCount--;
+ psDDRSetting++;
+ }
+ return retval;
+}
diff --git a/drivers/staging/bcm/DDRInit.h b/drivers/staging/bcm/DDRInit.h
new file mode 100644
index 00000000000..b0196fce925
--- /dev/null
+++ b/drivers/staging/bcm/DDRInit.h
@@ -0,0 +1,9 @@
+#ifndef _DDR_INIT_H_
+#define _DDR_INIT_H_
+
+
+
+int ddr_init(struct bcm_mini_adapter *psAdapter);
+int download_ddr_settings(struct bcm_mini_adapter *psAdapter);
+
+#endif
diff --git a/drivers/staging/bcm/Debug.h b/drivers/staging/bcm/Debug.h
new file mode 100644
index 00000000000..7b331215c1a
--- /dev/null
+++ b/drivers/staging/bcm/Debug.h
@@ -0,0 +1,242 @@
+/*
+ * Debug.h
+ *
+ * Dynamic (runtime) debug framework implementation.
+ * -kaiwan.
+ */
+#ifndef _DEBUG_H
+#define _DEBUG_H
+#include <linux/string.h>
+#define NONE 0xFFFF
+
+/* TYPE and SUBTYPE
+ * Define valid TYPE (or category or code-path, however you like to think of it)
+ * and SUBTYPE s.
+ * Type and SubType are treated as bitmasks.
+ */
+#define DBG_TYPE_INITEXIT (1 << 0) /* 1 */
+#define DBG_TYPE_TX (1 << 1) /* 2 */
+#define DBG_TYPE_RX (1 << 2) /* 4 */
+#define DBG_TYPE_OTHERS (1 << 3) /* 8 */
+#define NUMTYPES 4
+
+/* -SUBTYPEs for TX : TYPE is DBG_TYPE_TX -----//
+ * Transmit.c ,Arp.c, LeakyBucket.c, And Qos.c
+ * total 17 macros
+ */
+/* Transmit.c */
+#define TX 1
+#define MP_SEND (TX << 0)
+#define NEXT_SEND (TX << 1)
+#define TX_FIFO (TX << 2)
+#define TX_CONTROL (TX << 3)
+
+/* Arp.c */
+#define IP_ADDR (TX << 4)
+#define ARP_REQ (TX << 5)
+#define ARP_RESP (TX << 6)
+
+/* Leakybucket.c */
+#define TOKEN_COUNTS (TX << 8)
+#define CHECK_TOKENS (TX << 9)
+#define TX_PACKETS (TX << 10)
+#define TIMER (TX << 11)
+
+/* Qos.c */
+#define QOS TX
+#define QUEUE_INDEX (QOS << 12)
+#define IPV4_DBG (QOS << 13)
+#define IPV6_DBG (QOS << 14)
+#define PRUNE_QUEUE (QOS << 15)
+#define SEND_QUEUE (QOS << 16)
+
+/* TX_Misc */
+#define TX_OSAL_DBG (TX << 17)
+
+/* --SUBTYPEs for ------INIT & EXIT---------------------
+ * ------------ TYPE is DBG_TYPE_INITEXIT -----//
+ * DriverEntry.c, bcmfwup.c, ChipDetectTask.c, HaltnReset.c, InterfaceDDR.c
+ */
+#define MP 1
+#define DRV_ENTRY (MP << 0)
+#define MP_INIT (MP << 1)
+#define READ_REG (MP << 3)
+#define DISPATCH (MP << 2)
+#define CLAIM_ADAP (MP << 4)
+#define REG_IO_PORT (MP << 5)
+#define INIT_DISP (MP << 6)
+#define RX_INIT (MP << 7)
+
+/* -SUBTYPEs for --RX----------------------------------
+ * ------------RX : TYPE is DBG_TYPE_RX -----//
+ * Receive.c
+ */
+#define RX 1
+#define RX_DPC (RX << 0)
+#define RX_CTRL (RX << 3)
+#define RX_DATA (RX << 4)
+#define MP_RETURN (RX << 1)
+#define LINK_MSG (RX << 2)
+
+/* -SUBTYPEs for ----OTHER ROUTINES------------------
+ * ------------OTHERS : TYPE is DBG_TYPE_OTHER -----//
+ * HaltnReset,CheckForHang,PnP,Misc,CmHost
+ * total 12 macros
+ */
+#define OTHERS 1
+#define ISR OTHERS
+#define MP_DPC (ISR << 0)
+
+/* HaltnReset.c */
+#define HALT OTHERS
+#define MP_HALT (HALT << 1)
+#define CHECK_HANG (HALT << 2)
+#define MP_RESET (HALT << 3)
+#define MP_SHUTDOWN (HALT << 4)
+
+/* pnp.c */
+#define PNP OTHERS
+#define MP_PNP (PNP << 5)
+
+/* Misc.c */
+#define MISC OTHERS
+#define DUMP_INFO (MISC << 6)
+#define CLASSIFY (MISC << 7)
+#define LINK_UP_MSG (MISC << 8)
+#define CP_CTRL_PKT (MISC << 9)
+#define DUMP_CONTROL (MISC << 10)
+#define LED_DUMP_INFO (MISC << 11)
+
+/* CmHost.c */
+#define CMHOST OTHERS
+#define SERIAL (OTHERS << 12)
+#define IDLE_MODE (OTHERS << 13)
+#define WRM (OTHERS << 14)
+#define RDM (OTHERS << 15)
+
+/* TODO - put PHS_SEND in Tx PHS_RECEIVE in Rx path ? */
+#define PHS_SEND (OTHERS << 16)
+#define PHS_RECEIVE (OTHERS << 17)
+#define PHS_MODULE (OTHERS << 18)
+
+#define INTF_INIT (OTHERS << 19)
+#define INTF_ERR (OTHERS << 20)
+#define INTF_WARN (OTHERS << 21)
+#define INTF_NORM (OTHERS << 22)
+
+#define IRP_COMPLETION (OTHERS << 23)
+#define SF_DESCRIPTOR_CNTS (OTHERS << 24)
+#define PHS_DISPATCH (OTHERS << 25)
+#define OSAL_DBG (OTHERS << 26)
+#define NVM_RW (OTHERS << 27)
+
+#define HOST_MIBS (OTHERS << 28)
+#define CONN_MSG (CMHOST << 29)
+
+/* Debug level
+ * We have 8 debug levels, in (numerical) increasing order of verbosity.
+ * IMP: Currently implementing ONLY DBG_LVL_ALL , i.e. , all debug prints will
+ * appear (of course, iff global debug flag is ON and we match the Type and SubType).
+ * Finer granularity debug levels are currently not in use, although the feature exists.
+ *
+ * Another way to say this:
+ * All the debug prints currently have 'debug_level' set to DBG_LVL_ALL .
+ * You can compile-time change that to any of the below, if you wish to. However, as of now, there's
+ * no dynamic facility to have the userspace 'TestApp' set debug_level. Slated for future expansion.
+ */
+#define BCM_ALL 7
+#define BCM_LOW 6
+#define BCM_PRINT 5
+#define BCM_NORMAL 4
+#define BCM_MEDIUM 3
+#define BCM_SCREAM 2
+#define BCM_ERR 1
+/* Not meant for developer in debug prints.
+ * To be used to disable all prints by setting the DBG_LVL_CURR to this value
+ */
+#define BCM_NONE 0
+
+/* The current driver logging level.
+ * Everything at this level and (numerically) lower (meaning higher prio)
+ * is logged.
+ * Replace 'BCM_ALL' in the DBG_LVL_CURR macro with the logging level desired.
+ * For eg. to set the logging level to 'errors only' use:
+ * #define DBG_LVL_CURR (BCM_ERR)
+ */
+
+#define DBG_LVL_CURR (BCM_ALL)
+#define DBG_LVL_ALL BCM_ALL
+
+/* ---Userspace mapping of Debug State.
+ * Delibrately matches that of the Windows driver..
+ * The TestApp's ioctl passes this struct to us.
+ */
+struct bcm_user_debug_state {
+ unsigned int Subtype, Type;
+ unsigned int OnOff;
+/* unsigned int debug_level; future expansion */
+} __packed;
+
+/* ---Kernel-space mapping of Debug State */
+struct bcm_debug_state {
+ unsigned int type;
+ /* A bitmap of 32 bits for Subtype per Type.
+ * Valid indexes in 'subtype' array are *only* 1,2,4 and 8,
+ * corresponding to valid Type values. Hence we use the 'Type' field
+ * as the index value, ignoring the array entries 0,3,5,6,7 !
+ */
+ unsigned int subtype[(NUMTYPES*2)+1];
+ unsigned int debug_level;
+};
+/* Instantiated in the Adapter structure
+ * We'll reuse the debug level parameter to include a bit (the MSB) to indicate whether or not
+ * we want the function's name printed.
+ */
+#define DBG_NO_FUNC_PRINT (1 << 31)
+#define DBG_LVL_BITMASK 0xFF
+
+/* --- Only for direct printk's; "hidden" to API. */
+#define DBG_TYPE_PRINTK 3
+
+#define BCM_DEBUG_PRINT(Adapter, Type, SubType, dbg_level, string, args...) \
+ do { \
+ if (DBG_TYPE_PRINTK == Type) \
+ pr_info("%s:" string, __func__, ##args); \
+ else if (Adapter && \
+ (dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level && \
+ (Type & Adapter->stDebugState.type) && \
+ (SubType & Adapter->stDebugState.subtype[Type])) { \
+ if (dbg_level & DBG_NO_FUNC_PRINT) \
+ pr_debug("%s:\n", string); \
+ else \
+ pr_debug("%s:\n" string, __func__, ##args); \
+ } \
+ } while (0)
+
+#define BCM_DEBUG_PRINT_BUFFER(Adapter, Type, SubType, dbg_level, buffer, bufferlen) \
+ do { \
+ if (DBG_TYPE_PRINTK == Type || \
+ (Adapter && \
+ (dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level && \
+ (Type & Adapter->stDebugState.type) && \
+ (SubType & Adapter->stDebugState.subtype[Type]))) { \
+ pr_debug("%s:\n", __func__); \
+ print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, \
+ 16, 1, buffer, bufferlen, false); \
+ } \
+ } while (0)
+
+#define BCM_SHOW_DEBUG_BITMAP(Adapter) do { \
+ int i; \
+ for (i = 0; i < (NUMTYPES * 2) + 1; i++) { \
+ if ((i == 1) || (i == 2) || (i == 4) || (i == 8)) { \
+ /* CAUTION! Forcefully turn on ALL debug paths and subpaths! \
+ * Adapter->stDebugState.subtype[i] = 0xffffffff; \
+ */ \
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "subtype[%d] = 0x%08x\n", \
+ i, Adapter->stDebugState.subtype[i]); \
+ } \
+ } \
+} while (0)
+
+#endif
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c
new file mode 100644
index 00000000000..495fe3dc514
--- /dev/null
+++ b/drivers/staging/bcm/HandleControlPacket.c
@@ -0,0 +1,235 @@
+/**
+ * @file HandleControlPacket.c
+ * This file contains the routines to deal with
+ * sending and receiving of control packets.
+ */
+#include "headers.h"
+
+/**
+ * When a control packet is received, analyze the
+ * "status" and call appropriate response function.
+ * Enqueue the control packet for Application.
+ * @return None
+ */
+static VOID handle_rx_control_packet(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
+{
+ struct bcm_tarang_data *pTarang = NULL;
+ bool HighPriorityMessage = false;
+ struct sk_buff *newPacket = NULL;
+ CHAR cntrl_msg_mask_bit = 0;
+ bool drop_pkt_flag = TRUE;
+ USHORT usStatus = *(PUSHORT)(skb->data);
+
+ if (netif_msg_pktdata(Adapter))
+ print_hex_dump(KERN_DEBUG, PFX "rx control: ", DUMP_PREFIX_NONE,
+ 16, 1, skb->data, skb->len, 0);
+
+ switch (usStatus) {
+ case CM_RESPONSES: /* 0xA0 */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL,
+ "MAC Version Seems to be Non Multi-Classifier, rejected by Driver");
+ HighPriorityMessage = TRUE;
+ break;
+ case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
+ HighPriorityMessage = TRUE;
+ if (Adapter->LinkStatus == LINKUP_DONE)
+ CmControlResponseMessage(Adapter,
+ (skb->data + sizeof(USHORT)));
+ break;
+ case LINK_CONTROL_RESP: /* 0xA2 */
+ case STATUS_RSP: /* 0xA1 */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL, "LINK_CONTROL_RESP");
+ HighPriorityMessage = TRUE;
+ LinkControlResponseMessage(Adapter,
+ (skb->data + sizeof(USHORT)));
+ break;
+ case STATS_POINTER_RESP: /* 0xA6 */
+ HighPriorityMessage = TRUE;
+ StatisticsResponse(Adapter, (skb->data + sizeof(USHORT)));
+ break;
+ case IDLE_MODE_STATUS: /* 0xA3 */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL,
+ "IDLE_MODE_STATUS Type Message Got from F/W");
+ InterfaceIdleModeRespond(Adapter, (PUINT)(skb->data +
+ sizeof(USHORT)));
+ HighPriorityMessage = TRUE;
+ break;
+
+ case AUTH_SS_HOST_MSG:
+ HighPriorityMessage = TRUE;
+ break;
+
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL, "Got Default Response");
+ /* Let the Application Deal with This Packet */
+ break;
+ }
+
+ /* Queue The Control Packet to The Application Queues */
+ down(&Adapter->RxAppControlQueuelock);
+
+ for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) {
+ if (Adapter->device_removed)
+ break;
+
+ drop_pkt_flag = TRUE;
+ /*
+ * There are cntrl msg from A0 to AC. It has been mapped to 0 to
+ * C bit in the cntrl mask.
+ * Also, by default AD to BF has been masked to the rest of the
+ * bits... which wil be ON by default.
+ * if mask bit is enable to particular pkt status, send it out
+ * to app else stop it.
+ */
+ cntrl_msg_mask_bit = (usStatus & 0x1F);
+ /*
+ * printk("\ninew msg mask bit which is disable in mask:%X",
+ * cntrl_msg_mask_bit);
+ */
+ if (pTarang->RxCntrlMsgBitMask & (1 << cntrl_msg_mask_bit))
+ drop_pkt_flag = false;
+
+ if ((drop_pkt_flag == TRUE) ||
+ (pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN)
+ || ((pTarang->AppCtrlQueueLen >
+ MAX_APP_QUEUE_LEN / 2) &&
+ (HighPriorityMessage == false))) {
+ /*
+ * Assumption:-
+ * 1. every tarang manages it own dropped pkt
+ * statitistics
+ * 2. Total packet dropped per tarang will be equal to
+ * the sum of all types of dropped pkt by that
+ * tarang only.
+ */
+ switch (*(PUSHORT)skb->data) {
+ case CM_RESPONSES:
+ pTarang->stDroppedAppCntrlMsgs.cm_responses++;
+ break;
+ case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
+ pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++;
+ break;
+ case LINK_CONTROL_RESP:
+ pTarang->stDroppedAppCntrlMsgs.link_control_resp++;
+ break;
+ case STATUS_RSP:
+ pTarang->stDroppedAppCntrlMsgs.status_rsp++;
+ break;
+ case STATS_POINTER_RESP:
+ pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++;
+ break;
+ case IDLE_MODE_STATUS:
+ pTarang->stDroppedAppCntrlMsgs.idle_mode_status++;
+ break;
+ case AUTH_SS_HOST_MSG:
+ pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++;
+ break;
+ default:
+ pTarang->stDroppedAppCntrlMsgs.low_priority_message++;
+ break;
+ }
+
+ continue;
+ }
+
+ newPacket = skb_clone(skb, GFP_KERNEL);
+ if (!newPacket)
+ break;
+ ENQUEUEPACKET(pTarang->RxAppControlHead,
+ pTarang->RxAppControlTail, newPacket);
+ pTarang->AppCtrlQueueLen++;
+ }
+ up(&Adapter->RxAppControlQueuelock);
+ wake_up(&Adapter->process_read_wait_queue);
+ dev_kfree_skb(skb);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,
+ "After wake_up_interruptible");
+}
+
+/**
+ * @ingroup ctrl_pkt_functions
+ * Thread to handle control pkt reception
+ */
+int control_packet_handler(struct bcm_mini_adapter *Adapter /* pointer to adapter object*/)
+{
+ struct sk_buff *ctrl_packet = NULL;
+ unsigned long flags = 0;
+ /* struct timeval tv; */
+ /* int *puiBuffer = NULL; */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,
+ "Entering to make thread wait on control packet event!");
+ while (1) {
+ wait_event_interruptible(Adapter->process_rx_cntrlpkt,
+ atomic_read(&Adapter->cntrlpktCnt) ||
+ Adapter->bWakeUpDevice ||
+ kthread_should_stop());
+
+
+ if (kthread_should_stop()) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CP_CTRL_PKT,
+ DBG_LVL_ALL, "Exiting\n");
+ return 0;
+ }
+ if (TRUE == Adapter->bWakeUpDevice) {
+ Adapter->bWakeUpDevice = false;
+ if ((false == Adapter->bTriedToWakeUpFromlowPowerMode)
+ && ((TRUE == Adapter->IdleMode) ||
+ (TRUE == Adapter->bShutStatus))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ CP_CTRL_PKT, DBG_LVL_ALL,
+ "Calling InterfaceAbortIdlemode\n");
+ /*
+ * Adapter->bTriedToWakeUpFromlowPowerMode
+ * = TRUE;
+ */
+ InterfaceIdleModeWakeup(Adapter);
+ }
+ continue;
+ }
+
+ while (atomic_read(&Adapter->cntrlpktCnt)) {
+ spin_lock_irqsave(&Adapter->control_queue_lock, flags);
+ ctrl_packet = Adapter->RxControlHead;
+ if (ctrl_packet) {
+ DEQUEUEPACKET(Adapter->RxControlHead,
+ Adapter->RxControlTail);
+ /* Adapter->RxControlHead=ctrl_packet->next; */
+ }
+
+ spin_unlock_irqrestore(&Adapter->control_queue_lock,
+ flags);
+ handle_rx_control_packet(Adapter, ctrl_packet);
+ atomic_dec(&Adapter->cntrlpktCnt);
+ }
+
+ SetUpTargetDsxBuffers(Adapter);
+ }
+ return STATUS_SUCCESS;
+}
+
+INT flushAllAppQ(void)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_tarang_data *pTarang = NULL;
+ struct sk_buff *PacketToDrop = NULL;
+ for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) {
+ while (pTarang->RxAppControlHead != NULL) {
+ PacketToDrop = pTarang->RxAppControlHead;
+ DEQUEUEPACKET(pTarang->RxAppControlHead,
+ pTarang->RxAppControlTail);
+ dev_kfree_skb(PacketToDrop);
+ }
+ pTarang->AppCtrlQueueLen = 0;
+ /* dropped contrl packet statistics also should be reset. */
+ memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0,
+ sizeof(struct bcm_mibs_dropped_cntrl_msg));
+
+ }
+ return STATUS_SUCCESS;
+}
+
+
diff --git a/drivers/staging/bcm/HostMIBSInterface.h b/drivers/staging/bcm/HostMIBSInterface.h
new file mode 100644
index 00000000000..f922ac49b70
--- /dev/null
+++ b/drivers/staging/bcm/HostMIBSInterface.h
@@ -0,0 +1,192 @@
+#ifndef _HOST_MIBSINTERFACE_H
+#define _HOST_MIBSINTERFACE_H
+
+/*
+ * Copyright (c) 2007 Beceem Communications Pvt. Ltd
+ * File Name: HostMIBSInterface.h
+ * Abstract: This file contains DS used by the Host to update the Host
+ * statistics used for the MIBS.
+ */
+
+#define MIBS_MAX_CLASSIFIERS 100
+#define MIBS_MAX_PHSRULES 100
+#define MIBS_MAX_SERVICEFLOWS 17
+#define MIBS_MAX_IP_RANGE_LENGTH 4
+#define MIBS_MAX_PORT_RANGE 4
+#define MIBS_MAX_PROTOCOL_LENGTH 32
+#define MIBS_MAX_PHS_LENGTHS 255
+#define MIBS_IPV6_ADDRESS_SIZEINBYTES 0x10
+#define MIBS_IP_LENGTH_OF_ADDRESS 4
+#define MIBS_MAX_HIST_ENTRIES 12
+#define MIBS_PKTSIZEHIST_RANGE 128
+
+union bcm_mibs_ip_addr {
+ struct {
+ /* Source Ip Address Range */
+ unsigned long ulIpv4Addr[MIBS_MAX_IP_RANGE_LENGTH];
+ /* Source Ip Mask Address Range */
+ unsigned long ulIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH];
+ };
+ struct {
+ /* Source Ip Address Range */
+ unsigned long ulIpv6Addr[MIBS_MAX_IP_RANGE_LENGTH * 4];
+ /* Source Ip Mask Address Range */
+ unsigned long ulIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * 4];
+ };
+ struct {
+ unsigned char ucIpv4Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IP_LENGTH_OF_ADDRESS];
+ unsigned char ucIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IP_LENGTH_OF_ADDRESS];
+ };
+ struct {
+ unsigned char ucIpv6Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES];
+ unsigned char ucIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES];
+ };
+};
+
+struct bcm_mibs_host_info {
+ u64 GoodTransmits;
+ u64 GoodReceives;
+ /* this to keep track of the Tx and Rx MailBox Registers. */
+ unsigned long NumDesUsed;
+ unsigned long CurrNumFreeDesc;
+ unsigned long PrevNumFreeDesc;
+ /* to keep track the no of byte received */
+ unsigned long PrevNumRcevBytes;
+ unsigned long CurrNumRcevBytes;
+ /* QOS Related */
+ unsigned long BEBucketSize;
+ unsigned long rtPSBucketSize;
+ unsigned long LastTxQueueIndex;
+ bool TxOutofDescriptors;
+ bool TimerActive;
+ u32 u32TotalDSD;
+ u32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
+ u32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
+};
+
+struct bcm_mibs_classifier_rule {
+ unsigned long ulSFID;
+ unsigned char ucReserved[2];
+ u16 uiClassifierRuleIndex;
+ bool bUsed;
+ unsigned short usVCID_Value;
+ u8 u8ClassifierRulePriority;
+ union bcm_mibs_ip_addr stSrcIpAddress;
+ /* IP Source Address Length */
+ unsigned char ucIPSourceAddressLength;
+ union bcm_mibs_ip_addr stDestIpAddress;
+ /* IP Destination Address Length */
+ unsigned char ucIPDestinationAddressLength;
+ unsigned char ucIPTypeOfServiceLength;
+ unsigned char ucTosLow;
+ unsigned char ucTosHigh;
+ unsigned char ucTosMask;
+ unsigned char ucProtocolLength;
+ unsigned char ucProtocol[MIBS_MAX_PROTOCOL_LENGTH];
+ unsigned short usSrcPortRangeLo[MIBS_MAX_PORT_RANGE];
+ unsigned short usSrcPortRangeHi[MIBS_MAX_PORT_RANGE];
+ unsigned char ucSrcPortRangeLength;
+ unsigned short usDestPortRangeLo[MIBS_MAX_PORT_RANGE];
+ unsigned short usDestPortRangeHi[MIBS_MAX_PORT_RANGE];
+ unsigned char ucDestPortRangeLength;
+ bool bProtocolValid;
+ bool bTOSValid;
+ bool bDestIpValid;
+ bool bSrcIpValid;
+ unsigned char ucDirection;
+ bool bIpv6Protocol;
+ u32 u32PHSRuleID;
+};
+
+struct bcm_mibs_phs_rule {
+ unsigned long ulSFID;
+ u8 u8PHSI;
+ u8 u8PHSFLength;
+ u8 u8PHSF[MIBS_MAX_PHS_LENGTHS];
+ u8 u8PHSMLength;
+ u8 u8PHSM[MIBS_MAX_PHS_LENGTHS];
+ u8 u8PHSS;
+ u8 u8PHSV;
+ u8 reserved[5];
+ long PHSModifiedBytes;
+ unsigned long PHSModifiedNumPackets;
+ unsigned long PHSErrorNumPackets;
+};
+
+struct bcm_mibs_parameters {
+ u32 wmanIfSfid;
+ u32 wmanIfCmnCpsSfState;
+ u32 wmanIfCmnCpsMaxSustainedRate;
+ u32 wmanIfCmnCpsMaxTrafficBurst;
+ u32 wmanIfCmnCpsMinReservedRate;
+ u32 wmanIfCmnCpsToleratedJitter;
+ u32 wmanIfCmnCpsMaxLatency;
+ u32 wmanIfCmnCpsFixedVsVariableSduInd;
+ u32 wmanIfCmnCpsSduSize;
+ u32 wmanIfCmnCpsSfSchedulingType;
+ u32 wmanIfCmnCpsArqEnable;
+ u32 wmanIfCmnCpsArqWindowSize;
+ u32 wmanIfCmnCpsArqBlockLifetime;
+ u32 wmanIfCmnCpsArqSyncLossTimeout;
+ u32 wmanIfCmnCpsArqDeliverInOrder;
+ u32 wmanIfCmnCpsArqRxPurgeTimeout;
+ u32 wmanIfCmnCpsArqBlockSize;
+ u32 wmanIfCmnCpsMinRsvdTolerableRate;
+ u32 wmanIfCmnCpsReqTxPolicy;
+ u32 wmanIfCmnSfCsSpecification;
+ u32 wmanIfCmnCpsTargetSaid;
+};
+
+struct bcm_mibs_table {
+ unsigned long ulSFID;
+ unsigned short usVCID_Value;
+ unsigned int uiThreshold;
+ u8 u8TrafficPriority;
+ bool bValid;
+ bool bActive;
+ bool bActivateRequestSent;
+ u8 u8QueueType;
+ unsigned int uiMaxBucketSize;
+ unsigned int uiCurrentQueueDepthOnTarget;
+ unsigned int uiCurrentBytesOnHost;
+ unsigned int uiCurrentPacketsOnHost;
+ unsigned int uiDroppedCountBytes;
+ unsigned int uiDroppedCountPackets;
+ unsigned int uiSentBytes;
+ unsigned int uiSentPackets;
+ unsigned int uiCurrentDrainRate;
+ unsigned int uiThisPeriodSentBytes;
+ u64 liDrainCalculated;
+ unsigned int uiCurrentTokenCount;
+ u64 liLastUpdateTokenAt;
+ unsigned int uiMaxAllowedRate;
+ unsigned int NumOfPacketsSent;
+ unsigned char ucDirection;
+ unsigned short usCID;
+ struct bcm_mibs_parameters stMibsExtServiceFlowTable;
+ unsigned int uiCurrentRxRate;
+ unsigned int uiThisPeriodRxBytes;
+ unsigned int uiTotalRxBytes;
+ unsigned int uiTotalTxBytes;
+};
+
+struct bcm_mibs_dropped_cntrl_msg {
+ unsigned long cm_responses;
+ unsigned long cm_control_newdsx_multiclassifier_resp;
+ unsigned long link_control_resp;
+ unsigned long status_rsp;
+ unsigned long stats_pointer_resp;
+ unsigned long idle_mode_status;
+ unsigned long auth_ss_host_msg;
+ unsigned long low_priority_message;
+};
+
+struct bcm_host_stats_mibs {
+ struct bcm_mibs_host_info stHostInfo;
+ struct bcm_mibs_classifier_rule astClassifierTable[MIBS_MAX_CLASSIFIERS];
+ struct bcm_mibs_table astSFtable[MIBS_MAX_SERVICEFLOWS];
+ struct bcm_mibs_phs_rule astPhsRulesTable[MIBS_MAX_PHSRULES];
+ struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs;
+};
+
+#endif
diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c
new file mode 100644
index 00000000000..cd160670e02
--- /dev/null
+++ b/drivers/staging/bcm/IPv6Protocol.c
@@ -0,0 +1,451 @@
+#include "headers.h"
+
+static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+ struct bcm_ipv6_hdr *pstIpv6Header);
+static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+ struct bcm_ipv6_hdr *pstIpv6Header);
+static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header);
+
+static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
+ UCHAR *pucNextHeader, bool *bParseDone, USHORT *pusPayloadLength)
+{
+ UCHAR *pucRetHeaderPtr = NULL;
+ UCHAR *pucPayloadPtr = NULL;
+ USHORT usNextHeaderOffset = 0 ;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ if ((ppucPayload == NULL) || (*pusPayloadLength == 0) ||
+ (*bParseDone)) {
+ *bParseDone = TRUE;
+ return NULL;
+ }
+
+ pucRetHeaderPtr = *ppucPayload;
+ pucPayloadPtr = *ppucPayload;
+
+ if (!pucRetHeaderPtr || !pucPayloadPtr) {
+ *bParseDone = TRUE;
+ return NULL;
+ }
+
+ /* Get the Nextt Header Type */
+ *bParseDone = false;
+
+
+ switch (*pucNextHeader) {
+ case IPV6HDR_TYPE_HOPBYHOP:
+ {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 HopByHop Header");
+ usNextHeaderOffset += sizeof(struct bcm_ipv6_options_hdr);
+ }
+ break;
+
+ case IPV6HDR_TYPE_ROUTING:
+ {
+ struct bcm_ipv6_routing_hdr *pstIpv6RoutingHeader;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Routing Header");
+ pstIpv6RoutingHeader = (struct bcm_ipv6_routing_hdr *)pucPayloadPtr;
+ usNextHeaderOffset += sizeof(struct bcm_ipv6_routing_hdr);
+ usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES;
+
+ }
+ break;
+ case IPV6HDR_TYPE_FRAGMENTATION:
+ {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 Fragmentation Header");
+ usNextHeaderOffset += sizeof(struct bcm_ipv6_fragment_hdr);
+
+ }
+ break;
+ case IPV6HDR_TYPE_DESTOPTS:
+ {
+ struct bcm_ipv6_dest_options_hdr *pstIpv6DestOptsHdr = (struct bcm_ipv6_dest_options_hdr *)pucPayloadPtr;
+ int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 DestOpts Header Header");
+ usNextHeaderOffset += sizeof(struct bcm_ipv6_dest_options_hdr);
+ usNextHeaderOffset += nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
+
+ }
+ break;
+ case IPV6HDR_TYPE_AUTHENTICATION:
+ {
+ struct bcm_ipv6_authentication_hdr *pstIpv6AuthHdr = (struct bcm_ipv6_authentication_hdr *)pucPayloadPtr;
+ int nHdrLen = pstIpv6AuthHdr->ucLength;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 Authentication Header");
+ usNextHeaderOffset += nHdrLen * 4;
+ }
+ break;
+ case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
+ {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nIPv6 Encrypted Security Payload Header");
+ *bParseDone = TRUE;
+
+ }
+ break;
+ case IPV6_ICMP_HDR_TYPE:
+ {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nICMP Header");
+ *bParseDone = TRUE;
+ }
+ break;
+ case TCP_HEADER_TYPE:
+ {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nTCP Header");
+ *bParseDone = TRUE;
+ }
+ break;
+ case UDP_HEADER_TYPE:
+ {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nUDP Header");
+ *bParseDone = TRUE;
+ }
+ break;
+ default:
+ {
+ *bParseDone = TRUE;
+
+ }
+ break;
+
+
+ }
+
+ if (*bParseDone == false) {
+ if (*pusPayloadLength <= usNextHeaderOffset) {
+ *bParseDone = TRUE;
+ } else {
+ *pucNextHeader = *pucPayloadPtr;
+ pucPayloadPtr += usNextHeaderOffset;
+ (*pusPayloadLength) -= usNextHeaderOffset;
+ }
+
+ }
+
+ *ppucPayload = pucPayloadPtr;
+ return pucRetHeaderPtr;
+}
+
+
+static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort,
+ USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
+{
+ UCHAR *pIpv6HdrScanContext = pucPayload;
+ bool bDone = false;
+ UCHAR ucHeaderType = 0;
+ UCHAR *pucNextHeader = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ if (!pucPayload || (usPayloadLength == 0))
+ return 0;
+
+ *pusSrcPort = *pusDestPort = 0;
+ ucHeaderType = ucNextHeader;
+ while (!bDone) {
+ pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,
+ &ucHeaderType, &bDone, &usPayloadLength);
+ if (bDone) {
+ if ((ucHeaderType == TCP_HEADER_TYPE) ||
+ (ucHeaderType == UDP_HEADER_TYPE)) {
+ *pusSrcPort = *((PUSHORT)(pucNextHeader));
+ *pusDestPort = *((PUSHORT)(pucNextHeader+2));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "\nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",
+ ntohs(*pusSrcPort),
+ ntohs(*pusDestPort));
+ }
+ break;
+
+ }
+ }
+ return ucHeaderType;
+}
+
+
+/*
+ * Arg 1 struct bcm_mini_adapter *Adapter is a pointer ot the driver contorl structure
+ * Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet
+ */
+USHORT IpVersion6(struct bcm_mini_adapter *Adapter, PVOID pcIpHeader,
+ struct bcm_classifier_rule *pstClassifierRule)
+{
+ USHORT ushDestPort = 0;
+ USHORT ushSrcPort = 0;
+ UCHAR ucNextProtocolAboveIP = 0;
+ struct bcm_ipv6_hdr *pstIpv6Header = NULL;
+ bool bClassificationSucceed = false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "IpVersion6 ==========>\n");
+
+ pstIpv6Header = pcIpHeader;
+
+ DumpIpv6Header(pstIpv6Header);
+
+ /*
+ * Try to get the next higher layer protocol
+ * and the Ports Nos if TCP or UDP
+ */
+ ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(struct bcm_ipv6_hdr)),
+ &ushSrcPort,
+ &ushDestPort,
+ pstIpv6Header->usPayloadLength,
+ pstIpv6Header->ucNextHeader);
+
+ do {
+ if (pstClassifierRule->ucDirection == 0) {
+ /*
+ * cannot be processed for classification.
+ * it is a down link connection
+ */
+ break;
+ }
+
+ if (!pstClassifierRule->bIpv6Protocol) {
+ /*
+ * We are looking for Ipv6 Classifiers
+ * Lets ignore this classifier and try the next one
+ */
+ break;
+ }
+
+ bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
+ pstIpv6Header);
+ if (!bClassificationSucceed)
+ break;
+
+ bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
+ pstIpv6Header);
+ if (!bClassificationSucceed)
+ break;
+
+ /*
+ * Match the protocol type.
+ * For IPv6 the next protocol at end of
+ * Chain of IPv6 prot headers
+ */
+ bClassificationSucceed = MatchProtocol(pstClassifierRule,
+ ucNextProtocolAboveIP);
+ if (!bClassificationSucceed)
+ break;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Protocol Matched");
+
+ if ((ucNextProtocolAboveIP == TCP_HEADER_TYPE) ||
+ (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) {
+ /* Match Src Port */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",
+ ntohs(ushSrcPort));
+ bClassificationSucceed = MatchSrcPort(pstClassifierRule,
+ ntohs(ushSrcPort));
+ if (!bClassificationSucceed)
+ break;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Src Port Matched");
+
+ /* Match Dest Port */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",
+ ntohs(ushDestPort));
+ bClassificationSucceed = MatchDestPort(pstClassifierRule,
+ ntohs(ushDestPort));
+ if (!bClassificationSucceed)
+ break;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
+ }
+ } while (0);
+
+ if (bClassificationSucceed == TRUE) {
+ INT iMatchedSFQueueIndex = 0;
+ iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+ if (iMatchedSFQueueIndex >= NO_OF_QUEUES) {
+ bClassificationSucceed = false;
+ } else {
+ if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == false)
+ bClassificationSucceed = false;
+ }
+ }
+
+ return bClassificationSucceed;
+}
+
+
+static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+ struct bcm_ipv6_hdr *pstIpv6Header)
+{
+ UINT uiLoopIndex = 0;
+ UINT uiIpv6AddIndex = 0;
+ UINT uiIpv6AddrNoLongWords = 4;
+ ULONG aulSrcIP[4];
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ /*
+ * This is the no. of Src Addresses ie Range of IP Addresses contained
+ * in the classifier rule for which we need to match
+ */
+ UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength;
+
+
+ if (uiCountIPSrcAddresses == 0)
+ return TRUE;
+
+
+ /* First Convert the Ip Address in the packet to Host Endian order */
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
+ aulSrcIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < uiCountIPSrcAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Src Ipv6 Address In Received Packet :\n ");
+ DumpIpv6Address(aulSrcIP);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Src Ipv6 Mask In Classifier Rule:\n");
+ DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Src Ipv6 Address In Classifier Rule :\n");
+ DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]);
+
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+ if ((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
+ != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
+ /*
+ * Match failed for current Ipv6 Address
+ * Try next Ipv6 Address
+ */
+ break;
+ }
+
+ if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
+ /* Match Found */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "Ipv6 Src Ip Address Matched\n");
+ return TRUE;
+ }
+ }
+ }
+ return false;
+}
+
+static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+ struct bcm_ipv6_hdr *pstIpv6Header)
+{
+ UINT uiLoopIndex = 0;
+ UINT uiIpv6AddIndex = 0;
+ UINT uiIpv6AddrNoLongWords = 4;
+ ULONG aulDestIP[4];
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ /*
+ * This is the no. of Destination Addresses
+ * ie Range of IP Addresses contained in the classifier rule
+ * for which we need to match
+ */
+ UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength;
+
+
+ if (uiCountIPDestinationAddresses == 0)
+ return TRUE;
+
+
+ /* First Convert the Ip Address in the packet to Host Endian order */
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
+ aulDestIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < uiCountIPDestinationAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Destination Ipv6 Address In Received Packet :\n ");
+ DumpIpv6Address(aulDestIP);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Destination Ipv6 Mask In Classifier Rule :\n");
+ DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "\n Destination Ipv6 Address In Classifier Rule :\n");
+ DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]);
+
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+ if ((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
+ != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
+ /*
+ * Match failed for current Ipv6 Address.
+ * Try next Ipv6 Address
+ */
+ break;
+ }
+
+ if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
+ /* Match Found */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
+ DBG_LVL_ALL,
+ "Ipv6 Destination Ip Address Matched\n");
+ return TRUE;
+ }
+ }
+ }
+ return false;
+
+}
+
+VOID DumpIpv6Address(ULONG *puIpv6Address)
+{
+ UINT uiIpv6AddrNoLongWords = 4;
+ UINT uiIpv6AddIndex = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ ":%lx", puIpv6Address[uiIpv6AddIndex]);
+ }
+
+}
+
+static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header)
+{
+ UCHAR ucVersion;
+ UCHAR ucPrio;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "----Ipv6 Header---");
+ ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Version : %x\n", ucVersion);
+ ucPrio = pstIpv6Header->ucVersionPrio & 0x0f;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Priority : %x\n", ucPrio);
+ /*
+ * BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ * "Flow Label : %x\n",(pstIpv6Header->ucVersionPrio &0xf0);
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Payload Length : %x\n",
+ ntohs(pstIpv6Header->usPayloadLength));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Next Header : %x\n", pstIpv6Header->ucNextHeader);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Hop Limit : %x\n", pstIpv6Header->ucHopLimit);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Src Address :\n");
+ DumpIpv6Address(pstIpv6Header->ulSrcIpAddress);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "Dest Address :\n");
+ DumpIpv6Address(pstIpv6Header->ulDestIpAddress);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
+ "----Ipv6 Header End---");
+
+
+}
diff --git a/drivers/staging/bcm/IPv6ProtocolHdr.h b/drivers/staging/bcm/IPv6ProtocolHdr.h
new file mode 100644
index 00000000000..96b36a579af
--- /dev/null
+++ b/drivers/staging/bcm/IPv6ProtocolHdr.h
@@ -0,0 +1,85 @@
+#ifndef _IPV6_PROTOCOL_DEFINES_
+#define _IPV6_PROTOCOL_DEFINES_
+
+#define IPV6HDR_TYPE_HOPBYHOP 0x0
+#define IPV6HDR_TYPE_ROUTING 0x2B
+#define IPV6HDR_TYPE_FRAGMENTATION 0x2C
+#define IPV6HDR_TYPE_DESTOPTS 0x3c
+#define IPV6HDR_TYPE_AUTHENTICATION 0x33
+#define IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD 0x34
+#define MASK_IPV6_CS_SPEC 0x2
+
+#define TCP_HEADER_TYPE 0x6
+#define UDP_HEADER_TYPE 0x11
+#define IPV6_ICMP_HDR_TYPE 0x2
+#define IPV6_FLOWLABEL_BITOFFSET 9
+
+#define IPV6_MAX_CHAINEDHDR_BUFFBYTES 0x64
+/*
+ * Size of Dest Options field of Destinations Options Header
+ * in bytes.
+ */
+#define IPV6_DESTOPTS_HDR_OPTIONSIZE 0x8
+
+struct bcm_ipv6_hdr {
+ unsigned char ucVersionPrio;
+ unsigned char aucFlowLabel[3];
+ unsigned short usPayloadLength;
+ unsigned char ucNextHeader;
+ unsigned char ucHopLimit;
+ unsigned long ulSrcIpAddress[4];
+ unsigned long ulDestIpAddress[4];
+};
+
+struct bcm_ipv6_routing_hdr {
+ unsigned char ucNextHeader;
+ unsigned char ucRoutingType;
+ unsigned char ucNumAddresses;
+ unsigned char ucNextAddress;
+ unsigned long ulReserved;
+};
+
+struct bcm_ipv6_fragment_hdr {
+ unsigned char ucNextHeader;
+ unsigned char ucReserved;
+ unsigned short usFragmentOffset;
+ unsigned long ulIdentification;
+};
+
+struct bcm_ipv6_dest_options_hdr {
+ unsigned char ucNextHeader;
+ unsigned char ucHdrExtLen;
+ unsigned char ucDestOptions[6];
+};
+
+struct bcm_ipv6_options_hdr {
+ unsigned char ucNextHeader;
+ unsigned char ucMisc[3];
+ unsigned long ulJumboPayloadLen;
+};
+
+struct bcm_ipv6_authentication_hdr {
+ unsigned char ucNextHeader;
+ unsigned char ucLength;
+ unsigned short usReserved;
+ unsigned long ulSecurityParametersIndex;
+};
+
+enum bcm_ipaddr_context {
+ eSrcIpAddress,
+ eDestIpAddress
+};
+
+/* Function Prototypes */
+
+unsigned short IpVersion6(struct bcm_mini_adapter *Adapter, /* < Pointer to the driver control structure */
+ void *pcIpHeader, /* <Pointer to the IP Hdr of the packet */
+ struct bcm_classifier_rule *pstClassifierRule);
+
+void DumpIpv6Address(unsigned long *puIpv6Address);
+
+extern bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, unsigned short ushSrcPort);
+extern bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, unsigned short ushSrcPort);
+extern bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, unsigned char ucProtocol);
+
+#endif
diff --git a/drivers/staging/bcm/InterfaceAdapter.h b/drivers/staging/bcm/InterfaceAdapter.h
new file mode 100644
index 00000000000..06a6b18bca4
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceAdapter.h
@@ -0,0 +1,79 @@
+#ifndef _INTERFACE_ADAPTER_H
+#define _INTERFACE_ADAPTER_H
+
+struct bcm_bulk_endpoint_in {
+ char *bulk_in_buffer;
+ size_t bulk_in_size;
+ unsigned char bulk_in_endpointAddr;
+ unsigned int bulk_in_pipe;
+};
+
+struct bcm_bulk_endpoint_out {
+ unsigned char bulk_out_buffer;
+ size_t bulk_out_size;
+ unsigned char bulk_out_endpointAddr;
+ unsigned int bulk_out_pipe;
+ /* this is used when int out endpoint is used as bulk out end point */
+ unsigned char int_out_interval;
+};
+
+struct bcm_intr_endpoint_in {
+ char *int_in_buffer;
+ size_t int_in_size;
+ unsigned char int_in_endpointAddr;
+ unsigned char int_in_interval;
+ unsigned int int_in_pipe;
+};
+
+struct bcm_intr_endpoint_out {
+ char *int_out_buffer;
+ size_t int_out_size;
+ unsigned char int_out_endpointAddr;
+ unsigned char int_out_interval;
+ unsigned int int_out_pipe;
+};
+
+struct bcm_usb_tcb {
+ struct urb *urb;
+ void *psIntfAdapter;
+ bool bUsed;
+};
+
+struct bcm_usb_rcb {
+ struct urb *urb;
+ void *psIntfAdapter;
+ bool bUsed;
+};
+
+/*
+ * This is the interface specific Sub-Adapter
+ * Structure.
+ */
+struct bcm_interface_adapter {
+ struct usb_device *udev;
+ struct usb_interface *interface;
+ /* Bulk endpoint in info */
+ struct bcm_bulk_endpoint_in sBulkIn;
+ /* Bulk endpoint out info */
+ struct bcm_bulk_endpoint_out sBulkOut;
+ /* Interrupt endpoint in info */
+ struct bcm_intr_endpoint_in sIntrIn;
+ /* Interrupt endpoint out info */
+ struct bcm_intr_endpoint_out sIntrOut;
+ unsigned long ulInterruptData[2];
+ struct urb *psInterruptUrb;
+ struct bcm_usb_tcb asUsbTcb[MAXIMUM_USB_TCB];
+ struct bcm_usb_rcb asUsbRcb[MAXIMUM_USB_RCB];
+ atomic_t uNumTcbUsed;
+ atomic_t uCurrTcb;
+ atomic_t uNumRcbUsed;
+ atomic_t uCurrRcb;
+ struct bcm_mini_adapter *psAdapter;
+ bool bFlashBoot;
+ bool bHighSpeedDevice;
+ bool bSuspended;
+ bool bPreparingForBusSuspend;
+ struct work_struct usbSuspendWork;
+};
+
+#endif
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
new file mode 100644
index 00000000000..e1925bdc127
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -0,0 +1,316 @@
+#include "headers.h"
+
+int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
+{
+ /* unsigned int reg = 0; */
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0; /* ,is_config_file = 0 */
+ loff_t pos = 0;
+ struct bcm_interface_adapter *psIntfAdapter = arg;
+ /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */
+ char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+
+ if (!buff)
+ return -ENOMEM;
+
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff,
+ MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ if (len <= 0) {
+ if (len < 0)
+ errno = len;
+ else
+ errno = 0;
+ break;
+ }
+ /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
+ * DBG_LVL_ALL, buff,
+ * MAX_TRANSFER_CTRL_BYTE_USB);
+ */
+ errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
+ if (errno)
+ break;
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ }
+
+ kfree(buff);
+ return errno;
+}
+
+int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp,
+ unsigned int on_chip_loc)
+{
+ char *buff, *buff_readback;
+ unsigned int reg = 0;
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0, is_config_file = 0;
+ loff_t pos = 0;
+ static int fw_down;
+ INT Status = STATUS_SUCCESS;
+ struct bcm_interface_adapter *psIntfAdapter = arg;
+ int bytes;
+
+ buff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
+ buff_readback = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
+ if (!buff || !buff_readback) {
+ kfree(buff);
+ kfree(buff_readback);
+
+ return -ENOMEM;
+ }
+
+ is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
+
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff,
+ MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ fw_down++;
+
+ if (len <= 0) {
+ if (len < 0)
+ errno = len;
+ else
+ errno = 0;
+ break;
+ }
+
+ bytes = InterfaceRDM(psIntfAdapter, on_chip_loc,
+ buff_readback, len);
+ if (bytes < 0) {
+ Status = bytes;
+ goto exit;
+ }
+ reg++;
+ if ((len-sizeof(unsigned int)) < 4) {
+ if (memcmp(buff_readback, buff, len)) {
+ Status = -EIO;
+ goto exit;
+ }
+ } else {
+ len -= 4;
+
+ while (len) {
+ if (*(unsigned int *)&buff_readback[len] !=
+ *(unsigned int *)&buff[len]) {
+ Status = -EIO;
+ goto exit;
+ }
+ len -= 4;
+ }
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ } /* End of while(1) */
+
+exit:
+ kfree(buff);
+ kfree(buff_readback);
+ return Status;
+}
+
+static int bcm_download_config_file(struct bcm_mini_adapter *Adapter,
+ struct bcm_firmware_info *psFwInfo)
+{
+ int retval = STATUS_SUCCESS;
+ B_UINT32 value = 0;
+
+ if (Adapter->pstargetparams == NULL) {
+ Adapter->pstargetparams =
+ kmalloc(sizeof(struct bcm_target_params), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL)
+ return -ENOMEM;
+ }
+
+ if (psFwInfo->u32FirmwareLength != sizeof(struct bcm_target_params))
+ return -EIO;
+
+ retval = copy_from_user(Adapter->pstargetparams,
+ psFwInfo->pvMappedFirmwareAddress,
+ psFwInfo->u32FirmwareLength);
+ if (retval) {
+ kfree(Adapter->pstargetparams);
+ Adapter->pstargetparams = NULL;
+ return -EFAULT;
+ }
+
+ /* Parse the structure and then Download the Firmware */
+ beceem_parse_target_struct(Adapter);
+
+ /* Initializing the NVM. */
+ BcmInitNVM(Adapter);
+ retval = InitLedSettings(Adapter);
+
+ if (retval)
+ return retval;
+
+ if (Adapter->LEDInfo.led_thread_running &
+ BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->LEDInfo.bLedInitDone = false;
+ Adapter->DriverState = DRIVER_INIT;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ if (Adapter->LEDInfo.led_thread_running &
+ BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = FW_DOWNLOAD;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ /* Initialize the DDR Controller */
+ retval = ddr_init(Adapter);
+ if (retval)
+ return retval;
+
+ value = 0;
+ wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4,
+ &value, sizeof(value));
+ wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8,
+ &value, sizeof(value));
+
+ if (Adapter->eNVMType == NVM_FLASH) {
+ retval = PropagateCalParamsFromFlashToMemory(Adapter);
+ if (retval)
+ return retval;
+ }
+
+ retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams,
+ sizeof(struct bcm_target_params), CONFIG_BEGIN_ADDR);
+
+ if (retval)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT,
+ MP_INIT, DBG_LVL_ALL,
+ "configuration file not downloaded properly");
+ else
+ Adapter->bCfgDownloaded = TRUE;
+
+ return retval;
+}
+
+int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter,
+ struct bcm_firmware_info *psFwInfo)
+{
+ int retval = STATUS_SUCCESS;
+ PUCHAR buff = NULL;
+
+ /* Config File is needed for the Driver to download the Config file and
+ * Firmware. Check for the Config file to be first to be sent from the
+ * Application
+ */
+ atomic_set(&Adapter->uiMBupdate, false);
+ if (!Adapter->bCfgDownloaded &&
+ psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
+ /* Can't Download Firmware. */
+ return -EINVAL;
+ }
+
+ /* If Config File, Finish the DDR Settings and then Download CFG File */
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
+ retval = bcm_download_config_file(Adapter, psFwInfo);
+ } else {
+ buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
+ if (buff == NULL)
+ return -ENOMEM;
+
+ retval = copy_from_user(buff,
+ psFwInfo->pvMappedFirmwareAddress,
+ psFwInfo->u32FirmwareLength);
+ if (retval != STATUS_SUCCESS) {
+ retval = -EFAULT;
+ goto error;
+ }
+
+ retval = buffDnldVerify(Adapter,
+ buff,
+ psFwInfo->u32FirmwareLength,
+ psFwInfo->u32StartingAddress);
+
+ if (retval != STATUS_SUCCESS)
+ goto error;
+ }
+
+error:
+ kfree(buff);
+ return retval;
+}
+
+static INT buffDnld(struct bcm_mini_adapter *Adapter,
+ PUCHAR mappedbuffer, UINT u32FirmwareLength,
+ ULONG u32StartingAddress)
+{
+ unsigned int len = 0;
+ int retval = STATUS_SUCCESS;
+ len = u32FirmwareLength;
+
+ while (u32FirmwareLength) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
+
+ if (retval)
+ break;
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
+ }
+ return retval;
+}
+
+static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter,
+ PUCHAR mappedbuffer, UINT u32FirmwareLength,
+ ULONG u32StartingAddress)
+{
+ UINT len = u32FirmwareLength;
+ INT retval = STATUS_SUCCESS;
+ PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+ int bytes;
+
+ if (NULL == readbackbuff)
+ return -ENOMEM;
+
+ while (u32FirmwareLength && !retval) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
+
+ if (bytes < 0) {
+ retval = bytes;
+ break;
+ }
+
+ if (memcmp(readbackbuff, mappedbuffer, len) != 0) {
+ pr_err("%s() failed. The firmware doesn't match what was written",
+ __func__);
+ retval = -EIO;
+ }
+
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
+
+ } /* end of while (u32FirmwareLength && !retval) */
+ kfree(readbackbuff);
+ return retval;
+}
+
+INT buffDnldVerify(struct bcm_mini_adapter *Adapter,
+ unsigned char *mappedbuffer,
+ unsigned int u32FirmwareLength,
+ unsigned long u32StartingAddress)
+{
+ INT status = STATUS_SUCCESS;
+
+ status = buffDnld(Adapter, mappedbuffer,
+ u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS)
+ goto error;
+
+ status = buffRdbkVerify(Adapter, mappedbuffer,
+ u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS)
+ goto error;
+error:
+ return status;
+}
diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c
new file mode 100644
index 00000000000..c84ee494f55
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceIdleMode.c
@@ -0,0 +1,275 @@
+#include "headers.h"
+
+/*
+Function: InterfaceIdleModeWakeup
+
+Description: This is the hardware specific Function for
+ waking up HW device from Idle mode.
+ A software abort pattern is written to the
+ device to wake it and necessary power state
+ transitions from host are performed here.
+
+Input parameters: IN struct bcm_mini_adapter *Adapter
+ - Miniport Adapter Context
+
+Return: BCM_STATUS_SUCCESS - If Wakeup of the HW Interface
+ was successful.
+ Other - If an error occurred.
+*/
+
+/*
+Function: InterfaceIdleModeRespond
+
+Description: This is the hardware specific Function for
+ responding to Idle mode request from target.
+ Necessary power state transitions from host for
+ idle mode or other device specific initializations
+ are performed here.
+
+Input parameters: IN struct bcm_mini_adapter * Adapter
+ - Miniport Adapter Context
+
+Return: BCM_STATUS_SUCCESS - If Idle mode response related
+ HW configuration was successful.
+ Other - If an error occurred.
+*/
+
+/*
+"dmem bfc02f00 100" tells how many time device went in Idle mode.
+this value will be at address bfc02fa4.just before value d0ea1dle.
+
+Set time value by writing at bfc02f98 7d0
+
+checking the Ack timer expire on kannon by running command
+d qcslog .. if it shows e means host has not send response
+to f/w with in 200 ms. Response should be
+send to f/w with in 200 ms after the Idle/Shutdown req issued
+
+*/
+
+
+int InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter,
+ unsigned int *puiBuffer)
+{
+ int status = STATUS_SUCCESS;
+ unsigned int uiRegRead = 0;
+ int bytes;
+
+ if (ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD) {
+ if (ntohl(*(puiBuffer+1)) == 0) {
+
+ status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC,
+ &uiRegRead, sizeof(uiRegRead));
+ if (status)
+ return status;
+
+ if (Adapter->ulPowerSaveMode ==
+ DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
+ uiRegRead = 0x00000000;
+ status = wrmalt(Adapter,
+ DEBUG_INTERRUPT_GENERATOR_REGISTOR,
+ &uiRegRead, sizeof(uiRegRead));
+ if (status)
+ return status;
+ }
+ /* Below Register should not br read in case of
+ * Manual and Protocol Idle mode */
+ else if (Adapter->ulPowerSaveMode !=
+ DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
+ /* clear on read Register */
+ bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0,
+ &uiRegRead, sizeof(uiRegRead));
+ if (bytes < 0) {
+ status = bytes;
+ return status;
+ }
+ /* clear on read Register */
+ bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1,
+ &uiRegRead, sizeof(uiRegRead));
+ if (bytes < 0) {
+ status = bytes;
+ return status;
+ }
+ }
+
+ /* Set Idle Mode Flag to False and
+ * Clear IdleMode reg. */
+ Adapter->IdleMode = false;
+ Adapter->bTriedToWakeUpFromlowPowerMode = false;
+
+ wake_up(&Adapter->lowpower_mode_wait_queue);
+
+ } else {
+ if (TRUE == Adapter->IdleMode)
+ return status;
+
+ uiRegRead = 0;
+
+ if (Adapter->chip_id == BCS220_2 ||
+ Adapter->chip_id == BCS220_2BC ||
+ Adapter->chip_id == BCS250_BC ||
+ Adapter->chip_id == BCS220_3) {
+
+ bytes = rdmalt(Adapter, HPM_CONFIG_MSW,
+ &uiRegRead, sizeof(uiRegRead));
+ if (bytes < 0) {
+ status = bytes;
+ return status;
+ }
+
+
+ uiRegRead |= (1<<17);
+
+ status = wrmalt(Adapter, HPM_CONFIG_MSW,
+ &uiRegRead, sizeof(uiRegRead));
+ if (status)
+ return status;
+ }
+ SendIdleModeResponse(Adapter);
+ }
+ } else if (ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG) {
+ OverrideServiceFlowParams(Adapter, puiBuffer);
+ }
+ return status;
+}
+
+static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter,
+ unsigned int Pattern)
+{
+ int status = STATUS_SUCCESS;
+ unsigned int value;
+ unsigned int chip_id;
+ unsigned long timeout = 0, itr = 0;
+
+ int lenwritten = 0;
+ unsigned char aucAbortPattern[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF};
+ struct bcm_interface_adapter *psInterfaceAdapter =
+ Adapter->pvInterfaceAdapter;
+
+ /* Abort Bus suspend if its already suspended */
+ if ((TRUE == psInterfaceAdapter->bSuspended) &&
+ (TRUE == Adapter->bDoSuspend))
+ status = usb_autopm_get_interface(
+ psInterfaceAdapter->interface);
+
+ if ((Adapter->ulPowerSaveMode ==
+ DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) ||
+ (Adapter->ulPowerSaveMode ==
+ DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) {
+ /* write the SW abort pattern. */
+ status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC,
+ &Pattern, sizeof(Pattern));
+ if (status)
+ return status;
+ }
+
+ if (Adapter->ulPowerSaveMode ==
+ DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
+ value = 0x80000000;
+ status = wrmalt(Adapter,
+ DEBUG_INTERRUPT_GENERATOR_REGISTOR,
+ &value, sizeof(value));
+ if (status)
+ return status;
+ } else if (Adapter->ulPowerSaveMode !=
+ DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
+ /*
+ * Get a Interrupt Out URB and send 8 Bytes Down
+ * To be Done in Thread Context.
+ * Not using Asynchronous Mechanism.
+ */
+ status = usb_interrupt_msg(psInterfaceAdapter->udev,
+ usb_sndintpipe(psInterfaceAdapter->udev,
+ psInterfaceAdapter->sIntrOut.int_out_endpointAddr),
+ aucAbortPattern,
+ 8,
+ &lenwritten,
+ 5000);
+ if (status)
+ return status;
+ else
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ IDLE_MODE, DBG_LVL_ALL,
+ "NOB Sent down :%d", lenwritten);
+
+ /* mdelay(25); */
+
+ timeout = jiffies + msecs_to_jiffies(50);
+ while (time_after(timeout, jiffies)) {
+ itr++;
+ rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT));
+ if (0xbece3200 == (chip_id&~(0xF0)))
+ chip_id = chip_id&~(0xF0);
+ if (chip_id == Adapter->chip_id)
+ break;
+ }
+ if (time_before(timeout, jiffies))
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ IDLE_MODE, DBG_LVL_ALL,
+ "Not able to read chip-id even after 25 msec");
+ else
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ IDLE_MODE, DBG_LVL_ALL,
+ "Number of completed iteration to"
+ "read chip-id :%lu", itr);
+
+ status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC,
+ &Pattern, sizeof(status));
+ if (status)
+ return status;
+ }
+ return status;
+}
+int InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter)
+{
+ if (Adapter->bTriedToWakeUpFromlowPowerMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ IDLE_MODE, DBG_LVL_ALL,
+ "Wake up already attempted.. ignoring\n");
+ } else {
+ Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
+ InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern);
+
+ }
+ return 0;
+}
+
+void InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiRegVal = 0;
+ INT Status = 0;
+ int bytes;
+
+ if (Adapter->ulPowerSaveMode ==
+ DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
+ /* clear idlemode interrupt. */
+ uiRegVal = 0;
+ Status = wrmalt(Adapter,
+ DEBUG_INTERRUPT_GENERATOR_REGISTOR,
+ &uiRegVal, sizeof(uiRegVal));
+ if (Status)
+ return;
+ }
+
+ else {
+
+/* clear Interrupt EP registers. */
+ bytes = rdmalt(Adapter,
+ DEVICE_INT_OUT_EP_REG0,
+ &uiRegVal, sizeof(uiRegVal));
+ if (bytes < 0) {
+ Status = bytes;
+ return;
+ }
+
+ bytes = rdmalt(Adapter,
+ DEVICE_INT_OUT_EP_REG1,
+ &uiRegVal, sizeof(uiRegVal));
+ if (bytes < 0) {
+ Status = bytes;
+ return;
+ }
+ }
+}
+
diff --git a/drivers/staging/bcm/InterfaceIdleMode.h b/drivers/staging/bcm/InterfaceIdleMode.h
new file mode 100644
index 00000000000..2ef64003aa8
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceIdleMode.h
@@ -0,0 +1,15 @@
+#ifndef _INTERFACE_IDLEMODE_H
+#define _INTERFACE_IDLEMODE_H
+
+INT InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter);
+
+INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter,
+ unsigned int *puiBuffer);
+
+VOID InterfaceWriteIdleModeWakePattern(struct bcm_mini_adapter *Adapter);
+
+INT InterfaceWakeUp(struct bcm_mini_adapter *Adapter);
+
+VOID InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter);
+#endif
+
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
new file mode 100644
index 00000000000..7c04c73e3bc
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -0,0 +1,717 @@
+#include "headers.h"
+#include <linux/usb/ch9.h>
+static struct usb_device_id InterfaceUsbtable[] = {
+ { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SYM) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_TU25) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_226) },
+ { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_326) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, InterfaceUsbtable);
+
+static int debug = -1;
+module_param(debug, uint, 0600);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static const u32 default_msg =
+ NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+ | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
+ | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+
+static int InterfaceAdapterInit(struct bcm_interface_adapter *Adapter);
+
+static void InterfaceAdapterFree(struct bcm_interface_adapter *psIntfAdapter)
+{
+ int i = 0;
+
+ /* Wake up the wait_queue... */
+ if (psIntfAdapter->psAdapter->LEDInfo.led_thread_running &
+ BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ psIntfAdapter->psAdapter->DriverState = DRIVER_HALT;
+ wake_up(&psIntfAdapter->psAdapter->LEDInfo.notify_led_event);
+ }
+ reset_card_proc(psIntfAdapter->psAdapter);
+
+ /*
+ * worst case time taken by the RDM/WRM will be 5 sec. will check after
+ * every 100 ms to accertain the device is not being accessed. After
+ * this No RDM/WRM should be made.
+ */
+ while (psIntfAdapter->psAdapter->DeviceAccess) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT,
+ DRV_ENTRY, DBG_LVL_ALL,
+ "Device is being accessed.\n");
+ msleep(100);
+ }
+ /* Free interrupt URB */
+ /* psIntfAdapter->psAdapter->device_removed = TRUE; */
+ usb_free_urb(psIntfAdapter->psInterruptUrb);
+
+ /* Free transmit URBs */
+ for (i = 0; i < MAXIMUM_USB_TCB; i++) {
+ if (psIntfAdapter->asUsbTcb[i].urb != NULL) {
+ usb_free_urb(psIntfAdapter->asUsbTcb[i].urb);
+ psIntfAdapter->asUsbTcb[i].urb = NULL;
+ }
+ }
+ /* Free receive URB and buffers */
+ for (i = 0; i < MAXIMUM_USB_RCB; i++) {
+ if (psIntfAdapter->asUsbRcb[i].urb != NULL) {
+ kfree(psIntfAdapter->asUsbRcb[i].urb->transfer_buffer);
+ usb_free_urb(psIntfAdapter->asUsbRcb[i].urb);
+ psIntfAdapter->asUsbRcb[i].urb = NULL;
+ }
+ }
+ AdapterFree(psIntfAdapter->psAdapter);
+}
+
+static void ConfigureEndPointTypesThroughEEPROM(struct bcm_mini_adapter *Adapter)
+{
+ u32 ulReg;
+ int bytes;
+ struct bcm_interface_adapter *interfaceAdapter;
+
+ /* Program EP2 MAX_PKT_SIZE */
+ ulReg = ntohl(EP2_MPS_REG);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x128, 4, TRUE);
+ ulReg = ntohl(EP2_MPS);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x12C, 4, TRUE);
+
+ ulReg = ntohl(EP2_CFG_REG);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x132, 4, TRUE);
+ interfaceAdapter =
+ (struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter);
+ if (interfaceAdapter->bHighSpeedDevice) {
+ ulReg = ntohl(EP2_CFG_INT);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x136, 4, TRUE);
+ } else {
+ /* USE BULK EP as TX in FS mode. */
+ ulReg = ntohl(EP2_CFG_BULK);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x136, 4, TRUE);
+ }
+
+ /* Program EP4 MAX_PKT_SIZE. */
+ ulReg = ntohl(EP4_MPS_REG);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x13C, 4, TRUE);
+ ulReg = ntohl(EP4_MPS);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x140, 4, TRUE);
+
+ /* Program TX EP as interrupt(Alternate Setting) */
+ bytes = rdmalt(Adapter, 0x0F0110F8, &ulReg, sizeof(u32));
+ if (bytes < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL, "reading of Tx EP failed\n");
+ return;
+ }
+ ulReg |= 0x6;
+
+ ulReg = ntohl(ulReg);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1CC, 4, TRUE);
+
+ ulReg = ntohl(EP4_CFG_REG);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C8, 4, TRUE);
+ /* Program ISOCHRONOUS EP size to zero. */
+ ulReg = ntohl(ISO_MPS_REG);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1D2, 4, TRUE);
+ ulReg = ntohl(ISO_MPS);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1D6, 4, TRUE);
+
+ /*
+ * Update EEPROM Version.
+ * Read 4 bytes from 508 and modify 511 and 510.
+ */
+ ReadBeceemEEPROM(Adapter, 0x1FC, &ulReg);
+ ulReg &= 0x0101FFFF;
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1FC, 4, TRUE);
+
+ /* Update length field if required. Also make the string NULL terminated. */
+
+ ReadBeceemEEPROM(Adapter, 0xA8, &ulReg);
+ if ((ulReg&0x00FF0000)>>16 > 0x30) {
+ ulReg = (ulReg&0xFF00FFFF)|(0x30<<16);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0xA8, 4, TRUE);
+ }
+ ReadBeceemEEPROM(Adapter, 0x148, &ulReg);
+ if ((ulReg&0x00FF0000)>>16 > 0x30) {
+ ulReg = (ulReg&0xFF00FFFF)|(0x30<<16);
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x148, 4, TRUE);
+ }
+ ulReg = 0;
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x122, 4, TRUE);
+ ulReg = 0;
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE);
+}
+
+static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ int retval;
+ struct bcm_mini_adapter *psAdapter;
+ struct bcm_interface_adapter *psIntfAdapter;
+ struct net_device *ndev;
+
+ /* Reserve one extra queue for the bit-bucket */
+ ndev = alloc_etherdev_mq(sizeof(struct bcm_mini_adapter),
+ NO_OF_QUEUES + 1);
+ if (ndev == NULL) {
+ dev_err(&udev->dev, DRV_NAME ": no memory for device\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(ndev, &intf->dev);
+
+ psAdapter = netdev_priv(ndev);
+ psAdapter->dev = ndev;
+ psAdapter->msg_enable = netif_msg_init(debug, default_msg);
+
+ /* Init default driver debug state */
+
+ psAdapter->stDebugState.debug_level = DBG_LVL_CURR;
+ psAdapter->stDebugState.type = DBG_TYPE_INITEXIT;
+
+ /*
+ * Technically, one can start using BCM_DEBUG_PRINT after this point.
+ * However, realize that by default the Type/Subtype bitmaps are all
+ * zero now; so no prints will actually appear until the TestApp turns
+ * on debug paths via the ioctl(); so practically speaking, in early
+ * init, no logging happens.
+ *
+ * A solution (used below): we explicitly set the bitmaps to 1 for
+ * Type=DBG_TYPE_INITEXIT and ALL subtype's of the same. Now all bcm
+ * debug statements get logged, enabling debug during early init.
+ * Further, we turn this OFF once init_module() completes.
+ */
+
+ psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xff;
+ BCM_SHOW_DEBUG_BITMAP(psAdapter);
+
+ retval = InitAdapter(psAdapter);
+ if (retval) {
+ dev_err(&udev->dev, DRV_NAME ": InitAdapter Failed\n");
+ AdapterFree(psAdapter);
+ return retval;
+ }
+
+ /* Allocate interface adapter structure */
+ psIntfAdapter = kzalloc(sizeof(struct bcm_interface_adapter),
+ GFP_KERNEL);
+ if (psIntfAdapter == NULL) {
+ AdapterFree(psAdapter);
+ return -ENOMEM;
+ }
+
+ psAdapter->pvInterfaceAdapter = psIntfAdapter;
+ psIntfAdapter->psAdapter = psAdapter;
+
+ /* Store usb interface in Interface Adapter */
+ psIntfAdapter->interface = intf;
+ usb_set_intfdata(intf, psIntfAdapter);
+
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+ "psIntfAdapter 0x%p\n", psIntfAdapter);
+ retval = InterfaceAdapterInit(psIntfAdapter);
+ if (retval) {
+ /* If the Firmware/Cfg File is not present
+ * then return success, let the application
+ * download the files.
+ */
+ if (-ENOENT == retval) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "File Not Found. Use app to download.\n");
+ return STATUS_SUCCESS;
+ }
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL, "InterfaceAdapterInit failed.\n");
+ usb_set_intfdata(intf, NULL);
+ udev = interface_to_usbdev(intf);
+ usb_put_dev(udev);
+ InterfaceAdapterFree(psIntfAdapter);
+ return retval;
+ }
+ if (psAdapter->chip_id > T3) {
+ uint32_t uiNackZeroLengthInt = 4;
+
+ retval =
+ wrmalt(psAdapter, DISABLE_USB_ZERO_LEN_INT,
+ &uiNackZeroLengthInt,
+ sizeof(uiNackZeroLengthInt));
+ if (retval)
+ return retval;
+ }
+
+ /* Check whether the USB-Device Supports remote Wake-Up */
+ if (USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes) {
+ /* If Suspend then only support dynamic suspend */
+ if (psAdapter->bDoSuspend) {
+#ifdef CONFIG_PM
+ pm_runtime_set_autosuspend_delay(&udev->dev, 0);
+ intf->needs_remote_wakeup = 1;
+ usb_enable_autosuspend(udev);
+ device_init_wakeup(&intf->dev, 1);
+ INIT_WORK(&psIntfAdapter->usbSuspendWork,
+ putUsbSuspend);
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "Enabling USB Auto-Suspend\n");
+#endif
+ } else {
+ intf->needs_remote_wakeup = 0;
+ usb_disable_autosuspend(udev);
+ }
+ }
+
+ psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0x0;
+ return retval;
+}
+
+static void usbbcm_disconnect(struct usb_interface *intf)
+{
+ struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
+ struct bcm_mini_adapter *psAdapter;
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ if (psIntfAdapter == NULL)
+ return;
+
+ psAdapter = psIntfAdapter->psAdapter;
+ netif_device_detach(psAdapter->dev);
+
+ if (psAdapter->bDoSuspend)
+ intf->needs_remote_wakeup = 0;
+
+ psAdapter->device_removed = TRUE;
+ usb_set_intfdata(intf, NULL);
+ InterfaceAdapterFree(psIntfAdapter);
+ usb_put_dev(udev);
+}
+
+static int AllocUsbCb(struct bcm_interface_adapter *psIntfAdapter)
+{
+ int i = 0;
+
+ for (i = 0; i < MAXIMUM_USB_TCB; i++) {
+ psIntfAdapter->asUsbTcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbTcb[i].urb == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "Can't allocate Tx urb for index %d\n",
+ i);
+ return -ENOMEM;
+ }
+ }
+
+ for (i = 0; i < MAXIMUM_USB_RCB; i++) {
+ psIntfAdapter->asUsbRcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbRcb[i].urb == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "Can't allocate Rx urb for index %d\n",
+ i);
+ return -ENOMEM;
+ }
+
+ psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
+ kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbRcb[i].urb->transfer_buffer == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "Can't allocate Rx buffer for index %d\n",
+ i);
+ return -ENOMEM;
+ }
+ psIntfAdapter->asUsbRcb[i].urb->transfer_buffer_length =
+ MAX_DATA_BUFFER_SIZE;
+ }
+ return 0;
+}
+
+static int device_run(struct bcm_interface_adapter *psIntfAdapter)
+{
+ int value = 0;
+ UINT status = STATUS_SUCCESS;
+
+ status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter);
+ if (status != STATUS_SUCCESS) {
+ pr_err(DRV_NAME "InitCardAndDownloadFirmware failed.\n");
+ return status;
+ }
+ if (psIntfAdapter->psAdapter->fw_download_done) {
+ if (StartInterruptUrb(psIntfAdapter)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "Cannot send interrupt in URB\n");
+ }
+
+ /*
+ * now register the cntrl interface. after downloading the f/w
+ * waiting for 5 sec to get the mailbox interrupt.
+ */
+ psIntfAdapter->psAdapter->waiting_to_fw_download_done = false;
+ value = wait_event_timeout(
+ psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue,
+ psIntfAdapter->psAdapter->waiting_to_fw_download_done,
+ 5 * HZ);
+
+ if (value == 0)
+ pr_err(DRV_NAME ": Timeout waiting for mailbox interrupt.\n");
+
+ if (register_control_device_interface(
+ psIntfAdapter->psAdapter) < 0) {
+ pr_err(DRV_NAME ": Register Control Device failed.\n");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
+{
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ size_t buffer_size;
+ unsigned long value;
+ int retval = 0;
+ int usedIntOutForBulkTransfer = 0;
+ bool bBcm16 = false;
+ UINT uiData = 0;
+ int bytes;
+
+ /* Store the usb dev into interface adapter */
+ psIntfAdapter->udev =
+ usb_get_dev(interface_to_usbdev(psIntfAdapter->interface));
+
+ psIntfAdapter->bHighSpeedDevice =
+ (psIntfAdapter->udev->speed == USB_SPEED_HIGH);
+ psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
+ psIntfAdapter->psAdapter->interface_wrm = BcmWRM;
+
+ bytes = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG,
+ (u32 *) &(psIntfAdapter->psAdapter->chip_id),
+ sizeof(u32));
+ if (bytes < 0) {
+ retval = bytes;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+ "CHIP ID Read Failed\n");
+ return retval;
+ }
+
+ if (0xbece3200 == (psIntfAdapter->psAdapter->chip_id & ~(0xF0)))
+ psIntfAdapter->psAdapter->chip_id &= ~0xF0;
+
+ dev_info(&psIntfAdapter->udev->dev, "RDM Chip ID 0x%lx\n",
+ psIntfAdapter->psAdapter->chip_id);
+
+ iface_desc = psIntfAdapter->interface->cur_altsetting;
+
+ if (psIntfAdapter->psAdapter->chip_id == T3B) {
+ /* T3B device will have EEPROM, check if EEPROM is proper and
+ * BCM16 can be done or not. */
+ BeceemEEPROMBulkRead(psIntfAdapter->psAdapter, &uiData, 0x0, 4);
+ if (uiData == BECM)
+ bBcm16 = TRUE;
+
+ dev_info(&psIntfAdapter->udev->dev,
+ "number of alternate setting %d\n",
+ psIntfAdapter->interface->num_altsetting);
+
+ if (bBcm16 == TRUE) {
+ /* selecting alternate setting one as a default setting
+ * for High Speed modem. */
+ if (psIntfAdapter->bHighSpeedDevice)
+ retval = usb_set_interface(psIntfAdapter->udev,
+ DEFAULT_SETTING_0,
+ ALTERNATE_SETTING_1);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "BCM16 is applicable on this dongle\n");
+ if (retval || !psIntfAdapter->bHighSpeedDevice) {
+ usedIntOutForBulkTransfer = EP2;
+ endpoint = &iface_desc->endpoint[EP2].desc;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "Interface altsetting failed or modem is configured to Full Speed, hence will work on default setting 0\n");
+ /*
+ * If Modem is high speed device EP2 should be
+ * INT OUT End point
+ *
+ * If Mode is FS then EP2 should be bulk end
+ * point
+ */
+ if ((psIntfAdapter->bHighSpeedDevice &&
+ !usb_endpoint_is_int_out(endpoint)) ||
+ (!psIntfAdapter->bHighSpeedDevice &&
+ !usb_endpoint_is_bulk_out(endpoint))) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT,
+ DRV_ENTRY, DBG_LVL_ALL,
+ "Configuring the EEPROM\n");
+ /* change the EP2, EP4 to INT OUT end point */
+ ConfigureEndPointTypesThroughEEPROM(
+ psIntfAdapter->psAdapter);
+
+ /*
+ * It resets the device and if any thing
+ * gets changed in USB descriptor it
+ * will show fail and re-enumerate the
+ * device
+ */
+ retval = usb_reset_device(
+ psIntfAdapter->udev);
+ if (retval) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT,
+ DRV_ENTRY,
+ DBG_LVL_ALL,
+ "reset failed. Re-enumerating the device.\n");
+ return retval;
+ }
+
+ }
+ if (!psIntfAdapter->bHighSpeedDevice &&
+ usb_endpoint_is_bulk_out(endpoint)) {
+ /* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
+ UINT _uiData = ntohl(EP2_CFG_INT);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT,
+ DRV_ENTRY, DBG_LVL_ALL,
+ "Reverting Bulk to INT as it is in Full Speed mode.\n");
+ BeceemEEPROMBulkWrite(
+ psIntfAdapter->psAdapter,
+ (PUCHAR) & _uiData,
+ 0x136, 4, TRUE);
+ }
+ } else {
+ usedIntOutForBulkTransfer = EP4;
+ endpoint = &iface_desc->endpoint[EP4].desc;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "Choosing AltSetting as a default setting.\n");
+ if (!usb_endpoint_is_int_out(endpoint)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT,
+ DRV_ENTRY, DBG_LVL_ALL,
+ "Dongle does not have BCM16 Fix.\n");
+ /* change the EP2, EP4 to INT OUT end point and use EP4 in altsetting */
+ ConfigureEndPointTypesThroughEEPROM(
+ psIntfAdapter->psAdapter);
+
+ /*
+ * It resets the device and if any thing
+ * gets changed in USB descriptor it
+ * will show fail and re-enumerate the
+ * device
+ */
+ retval = usb_reset_device(
+ psIntfAdapter->udev);
+ if (retval) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT,
+ DRV_ENTRY,
+ DBG_LVL_ALL,
+ "reset failed. Re-enumerating the device.\n");
+ return retval;
+ }
+
+ }
+ }
+ }
+ }
+
+ iface_desc = psIntfAdapter->interface->cur_altsetting;
+
+ for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) {
+ endpoint = &iface_desc->endpoint[value].desc;
+
+ if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr &&
+ usb_endpoint_is_bulk_in(endpoint)) {
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
+ psIntfAdapter->sBulkIn.bulk_in_endpointAddr =
+ endpoint->bEndpointAddress;
+ psIntfAdapter->sBulkIn.bulk_in_pipe = usb_rcvbulkpipe(
+ psIntfAdapter->udev,
+ psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
+ }
+
+ if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
+ usb_endpoint_is_bulk_out(endpoint)) {
+ psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
+ endpoint->bEndpointAddress;
+ psIntfAdapter->sBulkOut.bulk_out_pipe = usb_sndbulkpipe(
+ psIntfAdapter->udev,
+ psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
+ }
+
+ if (!psIntfAdapter->sIntrIn.int_in_endpointAddr &&
+ usb_endpoint_is_int_in(endpoint)) {
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ psIntfAdapter->sIntrIn.int_in_size = buffer_size;
+ psIntfAdapter->sIntrIn.int_in_endpointAddr =
+ endpoint->bEndpointAddress;
+ psIntfAdapter->sIntrIn.int_in_interval =
+ endpoint->bInterval;
+ psIntfAdapter->sIntrIn.int_in_buffer =
+ kmalloc(buffer_size, GFP_KERNEL);
+ if (!psIntfAdapter->sIntrIn.int_in_buffer)
+ return -EINVAL;
+ }
+
+ if (!psIntfAdapter->sIntrOut.int_out_endpointAddr &&
+ usb_endpoint_is_int_out(endpoint)) {
+ if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
+ (psIntfAdapter->psAdapter->chip_id == T3B) &&
+ (value == usedIntOutForBulkTransfer)) {
+ /* use first intout end point as a bulk out end point */
+ buffer_size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ psIntfAdapter->sBulkOut.bulk_out_size =
+ buffer_size;
+ psIntfAdapter->sBulkOut.bulk_out_endpointAddr =
+ endpoint->bEndpointAddress;
+ psIntfAdapter->sBulkOut.bulk_out_pipe =
+ usb_sndintpipe(psIntfAdapter->udev,
+ psIntfAdapter->sBulkOut
+ .bulk_out_endpointAddr);
+ psIntfAdapter->sBulkOut.int_out_interval =
+ endpoint->bInterval;
+ } else if (value == EP6) {
+ buffer_size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ psIntfAdapter->sIntrOut.int_out_size =
+ buffer_size;
+ psIntfAdapter->sIntrOut.int_out_endpointAddr =
+ endpoint->bEndpointAddress;
+ psIntfAdapter->sIntrOut.int_out_interval =
+ endpoint->bInterval;
+ psIntfAdapter->sIntrOut.int_out_buffer =
+ kmalloc(buffer_size, GFP_KERNEL);
+ if (!psIntfAdapter->sIntrOut.int_out_buffer)
+ return -EINVAL;
+ }
+ }
+ }
+
+ usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter);
+
+ psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload;
+ psIntfAdapter->psAdapter->bcm_file_readback_from_chip =
+ InterfaceFileReadbackFromChip;
+ psIntfAdapter->psAdapter->interface_transmit = InterfaceTransmitPacket;
+
+ retval = CreateInterruptUrb(psIntfAdapter);
+
+ if (retval) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
+ "Cannot create interrupt urb\n");
+ return retval;
+ }
+
+ retval = AllocUsbCb(psIntfAdapter);
+ if (retval)
+ return retval;
+
+ return device_run(psIntfAdapter);
+}
+
+static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
+
+ psIntfAdapter->bSuspended = TRUE;
+
+ if (psIntfAdapter->bPreparingForBusSuspend) {
+ psIntfAdapter->bPreparingForBusSuspend = false;
+
+ if (psIntfAdapter->psAdapter->LinkStatus == LINKUP_DONE) {
+ psIntfAdapter->psAdapter->IdleMode = TRUE;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "Host Entered in PMU Idle Mode.\n");
+ } else {
+ psIntfAdapter->psAdapter->bShutStatus = TRUE;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, DRV_ENTRY,
+ DBG_LVL_ALL,
+ "Host Entered in PMU Shutdown Mode.\n");
+ }
+ }
+ psIntfAdapter->psAdapter->bPreparingForLowPowerMode = false;
+
+ /* Signaling the control pkt path */
+ wake_up(&psIntfAdapter->psAdapter->lowpower_mode_wait_queue);
+
+ return 0;
+}
+
+static int InterfaceResume(struct usb_interface *intf)
+{
+ struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
+
+ mdelay(100);
+ psIntfAdapter->bSuspended = false;
+
+ StartInterruptUrb(psIntfAdapter);
+ InterfaceRx(psIntfAdapter);
+ return 0;
+}
+
+static struct usb_driver usbbcm_driver = {
+ .name = "usbbcm",
+ .probe = usbbcm_device_probe,
+ .disconnect = usbbcm_disconnect,
+ .suspend = InterfaceSuspend,
+ .resume = InterfaceResume,
+ .id_table = InterfaceUsbtable,
+ .supports_autosuspend = 1,
+};
+
+struct class *bcm_class;
+
+static __init int bcm_init(void)
+{
+ int retval;
+
+ pr_info("%s: %s, %s\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION);
+ pr_info("%s\n", DRV_COPYRIGHT);
+
+ bcm_class = class_create(THIS_MODULE, DRV_NAME);
+ if (IS_ERR(bcm_class)) {
+ pr_err(DRV_NAME ": could not create class\n");
+ return PTR_ERR(bcm_class);
+ }
+
+ retval = usb_register(&usbbcm_driver);
+ if (retval < 0) {
+ pr_err(DRV_NAME ": could not register usb driver\n");
+ class_destroy(bcm_class);
+ return retval;
+ }
+ return 0;
+}
+
+static __exit void bcm_exit(void)
+{
+ usb_deregister(&usbbcm_driver);
+ class_destroy(bcm_class);
+}
+
+module_init(bcm_init);
+module_exit(bcm_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/bcm/InterfaceInit.h b/drivers/staging/bcm/InterfaceInit.h
new file mode 100644
index 00000000000..ffa6e9667ec
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceInit.h
@@ -0,0 +1,26 @@
+#ifndef _INTERFACE_INIT_H
+#define _INTERFACE_INIT_H
+
+#define BCM_USB_VENDOR_ID_T3 0x198f
+#define BCM_USB_VENDOR_ID_FOXCONN 0x0489
+#define BCM_USB_VENDOR_ID_ZTE 0x19d2
+
+#define BCM_USB_PRODUCT_ID_T3 0x0300
+#define BCM_USB_PRODUCT_ID_T3B 0x0210
+#define BCM_USB_PRODUCT_ID_T3L 0x0220
+#define BCM_USB_PRODUCT_ID_SYM 0x15E
+#define BCM_USB_PRODUCT_ID_1901 0xe017
+#define BCM_USB_PRODUCT_ID_226 0x0132 /* not sure if this is valid */
+#define BCM_USB_PRODUCT_ID_ZTE_226 0x172
+#define BCM_USB_PRODUCT_ID_ZTE_326 0x173 /* ZTE AX326 */
+#define BCM_USB_PRODUCT_ID_ZTE_TU25 0x0007
+
+#define BCM_USB_MINOR_BASE 192
+
+int InterfaceInitialize(void);
+
+int InterfaceExit(void);
+
+int usbbcm_worker_thread(struct bcm_interface_adapter *psIntfAdapter);
+
+#endif
diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c
new file mode 100644
index 00000000000..b9f8a7aa24f
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceIsr.c
@@ -0,0 +1,190 @@
+#include "headers.h"
+
+
+static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/)
+{
+ int status = urb->status;
+ struct bcm_interface_adapter *psIntfAdapter =
+ (struct bcm_interface_adapter *)urb->context;
+ struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
+
+ if (netif_msg_intr(Adapter))
+ pr_info(PFX "%s: interrupt status %d\n",
+ Adapter->dev->name, status);
+
+ if (Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL, "Device has Got Removed.");
+ return;
+ }
+
+ if ((Adapter->bPreparingForLowPowerMode && Adapter->bDoSuspend) ||
+ psIntfAdapter->bSuspended ||
+ psIntfAdapter->bPreparingForBusSuspend) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL,
+ "Interrupt call back is called while suspending the device");
+ return;
+ }
+
+ switch (status) {
+ /* success */
+ case STATUS_SUCCESS:
+ if (urb->actual_length) {
+
+ if (psIntfAdapter->ulInterruptData[1] & 0xFF) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ INTF_INIT, DBG_LVL_ALL,
+ "Got USIM interrupt");
+ }
+
+ if (psIntfAdapter->ulInterruptData[1] & 0xFF00) {
+ atomic_set(&Adapter->CurrNumFreeTxDesc,
+ (psIntfAdapter->ulInterruptData[1] &
+ 0xFF00) >> 8);
+ atomic_set(&Adapter->uiMBupdate, TRUE);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ INTF_INIT, DBG_LVL_ALL,
+ "TX mailbox contains %d",
+ atomic_read(&Adapter->CurrNumFreeTxDesc));
+ }
+ if (psIntfAdapter->ulInterruptData[1] >> 16) {
+ Adapter->CurrNumRecvDescs =
+ (psIntfAdapter->ulInterruptData[1] >> 16);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ INTF_INIT, DBG_LVL_ALL,
+ "RX mailbox contains %d",
+ Adapter->CurrNumRecvDescs);
+ InterfaceRx(psIntfAdapter);
+ }
+ if (Adapter->fw_download_done &&
+ !Adapter->downloadDDR &&
+ atomic_read(&Adapter->CurrNumFreeTxDesc)) {
+
+ psIntfAdapter->psAdapter->downloadDDR += 1;
+ wake_up(&Adapter->tx_packet_wait_queue);
+ }
+ if (!Adapter->waiting_to_fw_download_done) {
+ Adapter->waiting_to_fw_download_done = TRUE;
+ wake_up(&Adapter->ioctl_fw_dnld_wait_queue);
+ }
+ if (!atomic_read(&Adapter->TxPktAvail)) {
+ atomic_set(&Adapter->TxPktAvail, 1);
+ wake_up(&Adapter->tx_packet_wait_queue);
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL, "Firing interrupt in URB");
+ }
+ break;
+ case -ENOENT:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL, "URB has got disconnected....");
+ return;
+ case -EINPROGRESS:
+ /*
+ * This situation may happened when URBunlink is used. for
+ * detail check usb_unlink_urb documentation.
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL,
+ "Impossibe condition has occurred... something very bad is going on");
+ break;
+ /* return; */
+ case -EPIPE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL,
+ "Interrupt IN endPoint has got halted/stalled...need to clear this");
+ Adapter->bEndPointHalted = TRUE;
+ wake_up(&Adapter->tx_packet_wait_queue);
+ urb->status = STATUS_SUCCESS;
+ return;
+ /* software-driven interface shutdown */
+ case -ECONNRESET: /* URB got unlinked */
+ case -ESHUTDOWN: /* hardware gone. this is the serious problem */
+ /*
+ * Occurs only when something happens with the
+ * host controller device
+ */
+ case -ENODEV: /* Device got removed */
+ case -EINVAL:
+ /*
+ * Some thing very bad happened with the URB. No
+ * description is available.
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL, "interrupt urb error %d", status);
+ urb->status = STATUS_SUCCESS;
+ break;
+ /* return; */
+ default:
+ /*
+ * This is required to check what is the defaults conditions
+ * when it occurs..
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
+ "GOT DEFAULT INTERRUPT URB STATUS :%d..Please Analyze it...",
+ status);
+ break;
+ }
+
+ StartInterruptUrb(psIntfAdapter);
+
+
+}
+
+int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter)
+{
+ psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!psIntfAdapter->psInterruptUrb) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS,
+ INTF_INIT, DBG_LVL_ALL,
+ "Cannot allocate interrupt urb");
+ return -ENOMEM;
+ }
+ psIntfAdapter->psInterruptUrb->transfer_buffer =
+ psIntfAdapter->ulInterruptData;
+ psIntfAdapter->psInterruptUrb->transfer_buffer_length =
+ sizeof(psIntfAdapter->ulInterruptData);
+
+ psIntfAdapter->sIntrIn.int_in_pipe = usb_rcvintpipe(psIntfAdapter->udev,
+ psIntfAdapter->sIntrIn.int_in_endpointAddr);
+
+ usb_fill_int_urb(psIntfAdapter->psInterruptUrb, psIntfAdapter->udev,
+ psIntfAdapter->sIntrIn.int_in_pipe,
+ psIntfAdapter->psInterruptUrb->transfer_buffer,
+ psIntfAdapter->psInterruptUrb->transfer_buffer_length,
+ read_int_callback, psIntfAdapter,
+ psIntfAdapter->sIntrIn.int_in_interval);
+
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, INTF_INIT,
+ DBG_LVL_ALL, "Interrupt Interval: %d\n",
+ psIntfAdapter->sIntrIn.int_in_interval);
+ return 0;
+}
+
+
+INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter)
+{
+ INT status = 0;
+
+ if (!(psIntfAdapter->psAdapter->device_removed ||
+ psIntfAdapter->psAdapter->bEndPointHalted ||
+ psIntfAdapter->bSuspended ||
+ psIntfAdapter->bPreparingForBusSuspend ||
+ psIntfAdapter->psAdapter->StopAllXaction)) {
+ status =
+ usb_submit_urb(psIntfAdapter->psInterruptUrb, GFP_ATOMIC);
+ if (status) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,
+ "Cannot send inturb %d\n", status);
+ if (status == -EPIPE) {
+ psIntfAdapter->psAdapter->bEndPointHalted =
+ TRUE;
+ wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
+ }
+ }
+ }
+ return status;
+}
+
diff --git a/drivers/staging/bcm/InterfaceIsr.h b/drivers/staging/bcm/InterfaceIsr.h
new file mode 100644
index 00000000000..3073bd71cfe
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceIsr.h
@@ -0,0 +1,15 @@
+#ifndef _INTERFACE_ISR_H
+#define _INTERFACE_ISR_H
+
+int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter);
+
+
+INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter);
+
+
+VOID InterfaceEnableInterrupt(struct bcm_mini_adapter *Adapter);
+
+VOID InterfaceDisableInterrupt(struct bcm_mini_adapter *Adapter);
+
+#endif
+
diff --git a/drivers/staging/bcm/InterfaceMacros.h b/drivers/staging/bcm/InterfaceMacros.h
new file mode 100644
index 00000000000..7001caff9e2
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceMacros.h
@@ -0,0 +1,18 @@
+#ifndef _INTERFACE_MACROS_H
+#define _INTERFACE_MACROS_H
+
+#define BCM_USB_MAX_READ_LENGTH 2048
+
+#define MAXIMUM_USB_TCB 128
+#define MAXIMUM_USB_RCB 128
+
+#define MAX_BUFFERS_PER_QUEUE 256
+
+#define MAX_DATA_BUFFER_SIZE 2048
+
+//Num of Asynchronous reads pending
+#define NUM_RX_DESC 64
+
+#define SYS_CFG 0x0F000C00
+
+#endif
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
new file mode 100644
index 00000000000..4173fd7d671
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -0,0 +1,217 @@
+#include "headers.h"
+
+int InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter,
+ unsigned int addr,
+ void *buff,
+ int len)
+{
+ int bytes;
+
+ if (!psIntfAdapter)
+ return -EINVAL;
+
+ if (psIntfAdapter->psAdapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
+ return -ENODEV;
+ }
+
+ if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus");
+ return -EACCES;
+ }
+
+ if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
+ return -EACCES;
+ }
+ psIntfAdapter->psAdapter->DeviceAccess = TRUE;
+
+ bytes = usb_control_msg(psIntfAdapter->udev,
+ usb_rcvctrlpipe(psIntfAdapter->udev, 0),
+ 0x02,
+ 0xC2,
+ (addr & 0xFFFF),
+ ((addr >> 16) & 0xFFFF),
+ buff,
+ len,
+ 5000);
+
+ if (-ENODEV == bytes)
+ psIntfAdapter->psAdapter->device_removed = TRUE;
+
+ if (bytes < 0)
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes);
+ else
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
+
+ psIntfAdapter->psAdapter->DeviceAccess = false;
+ return bytes;
+}
+
+int InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter,
+ unsigned int addr,
+ void *buff,
+ int len)
+{
+ int retval = 0;
+
+ if (!psIntfAdapter)
+ return -EINVAL;
+
+ if (psIntfAdapter->psAdapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
+ return -ENODEV;
+ }
+
+ if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus...");
+ return -EACCES;
+ }
+
+ if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
+ return -EACCES;
+ }
+
+ psIntfAdapter->psAdapter->DeviceAccess = TRUE;
+
+ retval = usb_control_msg(psIntfAdapter->udev,
+ usb_sndctrlpipe(psIntfAdapter->udev, 0),
+ 0x01,
+ 0x42,
+ (addr & 0xFFFF),
+ ((addr >> 16) & 0xFFFF),
+ buff,
+ len,
+ 5000);
+
+ if (-ENODEV == retval)
+ psIntfAdapter->psAdapter->device_removed = TRUE;
+
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval);
+ psIntfAdapter->psAdapter->DeviceAccess = false;
+ return retval;
+ } else {
+ psIntfAdapter->psAdapter->DeviceAccess = false;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
+ return STATUS_SUCCESS;
+ }
+}
+
+int BcmRDM(void *arg,
+ unsigned int addr,
+ void *buff,
+ int len)
+{
+ return InterfaceRDM((struct bcm_interface_adapter *)arg, addr, buff, len);
+}
+
+int BcmWRM(void *arg,
+ unsigned int addr,
+ void *buff,
+ int len)
+{
+ return InterfaceWRM((struct bcm_interface_adapter *)arg, addr, buff, len);
+}
+
+int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter);
+ int status = STATUS_SUCCESS;
+
+ /*
+ * usb_clear_halt - tells device to clear endpoint halt/stall condition
+ * @dev: device whose endpoint is halted
+ * @pipe: endpoint "pipe" being cleared
+ * @ Context: !in_interrupt ()
+ *
+ * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
+ * This is used to clear halt conditions for bulk and interrupt endpoints only.
+ * Control and isochronous endpoints never halts.
+ *
+ * Any URBs queued for such an endpoint should normally be unlinked by the driver
+ * before clearing the halt condition.
+ *
+ */
+
+ /* Killing all the submitted urbs to different end points. */
+ Bcm_kill_all_URBs(psIntfAdapter);
+
+ /* clear the halted/stalled state for every end point */
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
+
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
+
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
+
+ return status;
+}
+
+void Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter)
+{
+ struct urb *tempUrb = NULL;
+ unsigned int i;
+
+ /*
+ * usb_kill_urb - cancel a transfer request and wait for it to finish
+ * @urb: pointer to URB describing a previously submitted request,
+ * returns nothing as it is void returned API.
+ *
+ * This routine cancels an in-progress request. It is guaranteed that
+ * upon return all completion handlers will have finished and the URB
+ * will be totally idle and available for reuse
+ *
+ * This routine may not be used in an interrupt context (such as a bottom
+ * half or a completion handler), or when holding a spinlock, or in other
+ * situations where the caller can't schedule().
+ *
+ */
+
+ /* Cancel submitted Interrupt-URB's */
+ if (psIntfAdapter->psInterruptUrb) {
+ if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
+ usb_kill_urb(psIntfAdapter->psInterruptUrb);
+ }
+
+ /* Cancel All submitted TX URB's */
+ for (i = 0; i < MAXIMUM_USB_TCB; i++) {
+ tempUrb = psIntfAdapter->asUsbTcb[i].urb;
+ if (tempUrb) {
+ if (tempUrb->status == -EINPROGRESS)
+ usb_kill_urb(tempUrb);
+ }
+ }
+
+ for (i = 0; i < MAXIMUM_USB_RCB; i++) {
+ tempUrb = psIntfAdapter->asUsbRcb[i].urb;
+ if (tempUrb) {
+ if (tempUrb->status == -EINPROGRESS)
+ usb_kill_urb(tempUrb);
+ }
+ }
+
+ atomic_set(&psIntfAdapter->uNumTcbUsed, 0);
+ atomic_set(&psIntfAdapter->uCurrTcb, 0);
+
+ atomic_set(&psIntfAdapter->uNumRcbUsed, 0);
+ atomic_set(&psIntfAdapter->uCurrRcb, 0);
+}
+
+void putUsbSuspend(struct work_struct *work)
+{
+ struct bcm_interface_adapter *psIntfAdapter = NULL;
+ struct usb_interface *intf = NULL;
+ psIntfAdapter = container_of(work, struct bcm_interface_adapter, usbSuspendWork);
+ intf = psIntfAdapter->interface;
+
+ if (psIntfAdapter->bSuspended == false)
+ usb_autopm_put_interface(intf);
+}
+
diff --git a/drivers/staging/bcm/InterfaceMisc.h b/drivers/staging/bcm/InterfaceMisc.h
new file mode 100644
index 00000000000..efb68604615
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceMisc.h
@@ -0,0 +1,42 @@
+#ifndef __INTERFACE_MISC_H
+#define __INTERFACE_MISC_H
+
+INT
+InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter,
+ UINT addr,
+ PVOID buff,
+ INT len);
+
+INT
+InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter,
+ UINT addr,
+ PVOID buff,
+ INT len);
+
+
+int InterfaceFileDownload(PVOID psIntfAdapter,
+ struct file *flp,
+ unsigned int on_chip_loc);
+
+int InterfaceFileReadbackFromChip(PVOID psIntfAdapter,
+ struct file *flp,
+ unsigned int on_chip_loc);
+
+
+int BcmRDM(PVOID arg,
+ UINT addr,
+ PVOID buff,
+ INT len);
+
+int BcmWRM(PVOID arg,
+ UINT addr,
+ PVOID buff,
+ INT len);
+
+INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter);
+
+VOID Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter);
+
+#define DISABLE_USB_ZERO_LEN_INT 0x0F011878
+
+#endif // __INTERFACE_MISC_H
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c
new file mode 100644
index 00000000000..11008173f91
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceRx.c
@@ -0,0 +1,233 @@
+#include "headers.h"
+
+static int SearchVcid(struct bcm_mini_adapter *Adapter, unsigned short usVcid)
+{
+ int iIndex = 0;
+
+ for (iIndex = (NO_OF_QUEUES-1); iIndex >= 0; iIndex--)
+ if (Adapter->PackInfo[iIndex].usVCID_Value == usVcid)
+ return iIndex;
+ return NO_OF_QUEUES+1;
+
+}
+
+
+static struct bcm_usb_rcb *
+GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter)
+{
+ struct bcm_usb_rcb *pRcb = NULL;
+ UINT index = 0;
+
+ if ((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) &&
+ (psIntfAdapter->psAdapter->StopAllXaction == false)) {
+ index = atomic_read(&psIntfAdapter->uCurrRcb);
+ pRcb = &psIntfAdapter->asUsbRcb[index];
+ pRcb->bUsed = TRUE;
+ pRcb->psIntfAdapter = psIntfAdapter;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d",
+ index, atomic_read(&psIntfAdapter->uNumRcbUsed));
+ index = (index + 1) % MAXIMUM_USB_RCB;
+ atomic_set(&psIntfAdapter->uCurrRcb, index);
+ atomic_inc(&psIntfAdapter->uNumRcbUsed);
+ }
+ return pRcb;
+}
+
+/*this is receive call back - when pkt available for receive (BULK IN- end point)*/
+static void read_bulk_callback(struct urb *urb)
+{
+ struct sk_buff *skb = NULL;
+ bool bHeaderSupressionEnabled = false;
+ int QueueIndex = NO_OF_QUEUES + 1;
+ UINT uiIndex = 0;
+ int process_done = 1;
+ struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context;
+ struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter;
+ struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
+ struct bcm_leader *pLeader = urb->transfer_buffer;
+
+ if (unlikely(netif_msg_rx_status(Adapter)))
+ pr_info(PFX "%s: rx urb status %d length %d\n",
+ Adapter->dev->name, urb->status, urb->actual_length);
+
+ if ((Adapter->device_removed == TRUE) ||
+ (TRUE == Adapter->bEndPointHalted) ||
+ (0 == urb->actual_length)) {
+ pRcb->bUsed = false;
+ atomic_dec(&psIntfAdapter->uNumRcbUsed);
+ return;
+ }
+
+ if (urb->status != STATUS_SUCCESS) {
+ if (urb->status == -EPIPE) {
+ Adapter->bEndPointHalted = TRUE;
+ wake_up(&Adapter->tx_packet_wait_queue);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Rx URB has got cancelled. status :%d", urb->status);
+ }
+ pRcb->bUsed = false;
+ atomic_dec(&psIntfAdapter->uNumRcbUsed);
+ urb->status = STATUS_SUCCESS;
+ return;
+ }
+
+ if (Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "device is going in low power mode while PMU option selected..hence rx packet should not be process");
+ return;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength);
+ if (!pLeader->PLength) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0");
+ atomic_dec(&psIntfAdapter->uNumRcbUsed);
+ return;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status, pLeader->PLength, pLeader->Vcid);
+ if (MAX_CNTL_PKT_SIZE < pLeader->PLength) {
+ if (netif_msg_rx_err(Adapter))
+ pr_info(PFX "%s: corrupted leader length...%d\n",
+ Adapter->dev->name, pLeader->PLength);
+ ++Adapter->dev->stats.rx_dropped;
+ atomic_dec(&psIntfAdapter->uNumRcbUsed);
+ return;
+ }
+
+ QueueIndex = SearchVcid(Adapter, pLeader->Vcid);
+ if (QueueIndex < NO_OF_QUEUES) {
+ bHeaderSupressionEnabled =
+ Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
+ bHeaderSupressionEnabled =
+ bHeaderSupressionEnabled & Adapter->bPHSEnabled;
+ }
+
+ skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER);
+ if (!skb) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet");
+ atomic_dec(&psIntfAdapter->uNumRcbUsed);
+ return;
+ }
+ /* If it is a control Packet, then call handle_bcm_packet ()*/
+ if ((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) ||
+ (!(pLeader->Status >= 0x20 && pLeader->Status <= 0x3F))) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt...");
+ *(PUSHORT)skb->data = pLeader->Status;
+ memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
+ (sizeof(struct bcm_leader)), pLeader->PLength);
+ skb->len = pLeader->PLength + sizeof(USHORT);
+
+ spin_lock(&Adapter->control_queue_lock);
+ ENQUEUEPACKET(Adapter->RxControlHead, Adapter->RxControlTail, skb);
+ spin_unlock(&Adapter->control_queue_lock);
+
+ atomic_inc(&Adapter->cntrlpktCnt);
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ } else {
+ /*
+ * Data Packet, Format a proper Ethernet Header
+ * and give it to the stack
+ */
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt...");
+ skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
+ memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(struct bcm_leader), pLeader->PLength);
+ skb->dev = Adapter->dev;
+
+ /* currently skb->len has extra ETH_HLEN bytes in the beginning */
+ skb_put(skb, pLeader->PLength + ETH_HLEN);
+ Adapter->PackInfo[QueueIndex].uiTotalRxBytes += pLeader->PLength;
+ Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes += pLeader->PLength;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength);
+
+ if (netif_running(Adapter->dev)) {
+ /* Moving ahead by ETH_HLEN to the data ptr as received from FW */
+ skb_pull(skb, ETH_HLEN);
+ PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
+ NULL, bHeaderSupressionEnabled);
+
+ if (!Adapter->PackInfo[QueueIndex].bEthCSSupport) {
+ skb_push(skb, ETH_HLEN);
+
+ memcpy(skb->data, skb->dev->dev_addr, 6);
+ memcpy(skb->data+6, skb->dev->dev_addr, 6);
+ (*(skb->data+11))++;
+ *(skb->data+12) = 0x08;
+ *(skb->data+13) = 0x00;
+ pLeader->PLength += ETH_HLEN;
+ }
+
+ skb->protocol = eth_type_trans(skb, Adapter->dev);
+ process_done = netif_rx(skb);
+ } else {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB...");
+ dev_kfree_skb(skb);
+ }
+
+ ++Adapter->dev->stats.rx_packets;
+ Adapter->dev->stats.rx_bytes += pLeader->PLength;
+
+ for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
+ if ((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) &&
+ (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
+ Adapter->aRxPktSizeHist[uiIndex]++;
+ }
+ }
+ Adapter->PrevNumRecvDescs++;
+ pRcb->bUsed = false;
+ atomic_dec(&psIntfAdapter->uNumRcbUsed);
+}
+
+static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_rcb *pRcb)
+{
+ struct urb *urb = pRcb->urb;
+ int retval = 0;
+
+ usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
+ urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback, pRcb);
+ if (false == psIntfAdapter->psAdapter->device_removed &&
+ false == psIntfAdapter->psAdapter->bEndPointHalted &&
+ false == psIntfAdapter->bSuspended &&
+ false == psIntfAdapter->bPreparingForBusSuspend) {
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval);
+ /* if this return value is because of pipe halt. need to clear this. */
+ if (retval == -EPIPE) {
+ psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
+ wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
+ }
+
+ }
+ }
+ return retval;
+}
+
+/*
+Function: InterfaceRx
+
+Description: This is the hardware specific Function for Receiving
+ data packet/control packets from the device.
+
+Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
+
+
+
+Return: TRUE - If Rx was successful.
+ Other - If an error occurred.
+*/
+
+bool InterfaceRx(struct bcm_interface_adapter *psIntfAdapter)
+{
+ USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed);
+ struct bcm_usb_rcb *pRcb = NULL;
+
+ while (RxDescCount) {
+ pRcb = GetBulkInRcb(psIntfAdapter);
+ if (pRcb == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer");
+ return false;
+ }
+ ReceiveRcb(psIntfAdapter, pRcb);
+ RxDescCount--;
+ }
+ return TRUE;
+}
+
diff --git a/drivers/staging/bcm/InterfaceRx.h b/drivers/staging/bcm/InterfaceRx.h
new file mode 100644
index 00000000000..b4e858bcda3
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceRx.h
@@ -0,0 +1,7 @@
+#ifndef _INTERFACE_RX_H
+#define _INTERFACE_RX_H
+
+bool InterfaceRx(struct bcm_interface_adapter *Adapter);
+
+#endif
+
diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c
new file mode 100644
index 00000000000..ea7707b8e60
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceTx.c
@@ -0,0 +1,174 @@
+#include "headers.h"
+
+/*this is transmit call-back(BULK OUT)*/
+static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
+{
+ struct bcm_usb_tcb *pTcb = (struct bcm_usb_tcb *)urb->context;
+ struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
+ struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer;
+ struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter;
+ bool bpowerDownMsg = false;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ if (unlikely(netif_msg_tx_done(Adapter)))
+ pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status);
+
+ if (urb->status != STATUS_SUCCESS) {
+ if (urb->status == -EPIPE) {
+ psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
+ wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx URB has got cancelled. status :%d", urb->status);
+ }
+ }
+
+ pTcb->bUsed = false;
+ atomic_dec(&psIntfAdapter->uNumTcbUsed);
+
+
+
+ if (TRUE == psAdapter->bPreparingForLowPowerMode) {
+
+ if (((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
+ (pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
+ bpowerDownMsg = TRUE;
+ /* This covers the bus err while Idle Request msg sent down. */
+ if (urb->status != STATUS_SUCCESS) {
+ psAdapter->bPreparingForLowPowerMode = false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Idle Mode Request msg failed to reach to Modem");
+ /* Signalling the cntrl pkt path in Ioctl */
+ wake_up(&psAdapter->lowpower_mode_wait_queue);
+ StartInterruptUrb(psIntfAdapter);
+ goto err_exit;
+ }
+
+ if (psAdapter->bDoSuspend == false) {
+ psAdapter->IdleMode = TRUE;
+ /* since going in Idle mode completed hence making this var false */
+ psAdapter->bPreparingForLowPowerMode = false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State...");
+ /* Signalling the cntrl pkt path in Ioctl*/
+ wake_up(&psAdapter->lowpower_mode_wait_queue);
+ }
+
+ } else if ((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) &&
+ (pControlMsg->szData[0] == LINK_UP_ACK) &&
+ (pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) &&
+ (pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
+ /* This covers the bus err while shutdown Request msg sent down. */
+ if (urb->status != STATUS_SUCCESS) {
+ psAdapter->bPreparingForLowPowerMode = false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Shutdown Request Msg failed to reach to Modem");
+ /* Signalling the cntrl pkt path in Ioctl */
+ wake_up(&psAdapter->lowpower_mode_wait_queue);
+ StartInterruptUrb(psIntfAdapter);
+ goto err_exit;
+ }
+
+ bpowerDownMsg = TRUE;
+ if (psAdapter->bDoSuspend == false) {
+ psAdapter->bShutStatus = TRUE;
+ /* since going in shutdown mode completed hence making this var false */
+ psAdapter->bPreparingForLowPowerMode = false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in shutdown Mode State...");
+ /* Signalling the cntrl pkt path in Ioctl */
+ wake_up(&psAdapter->lowpower_mode_wait_queue);
+ }
+ }
+
+ if (psAdapter->bDoSuspend && bpowerDownMsg) {
+ /* issuing bus suspend request */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Issuing the Bus suspend request to USB stack");
+ psIntfAdapter->bPreparingForBusSuspend = TRUE;
+ schedule_work(&psIntfAdapter->usbSuspendWork);
+
+ }
+
+ }
+
+err_exit:
+ usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
+}
+
+
+static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
+{
+ struct bcm_usb_tcb *pTcb = NULL;
+ UINT index = 0;
+
+ if ((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
+ (psIntfAdapter->psAdapter->StopAllXaction == false)) {
+ index = atomic_read(&psIntfAdapter->uCurrTcb);
+ pTcb = &psIntfAdapter->asUsbTcb[index];
+ pTcb->bUsed = TRUE;
+ pTcb->psIntfAdapter = psIntfAdapter;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got Tx desc %d used %d",
+ index, atomic_read(&psIntfAdapter->uNumTcbUsed));
+ index = (index + 1) % MAXIMUM_USB_TCB;
+ atomic_set(&psIntfAdapter->uCurrTcb, index);
+ atomic_inc(&psIntfAdapter->uNumTcbUsed);
+ }
+ return pTcb;
+}
+
+static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len)
+{
+
+ struct urb *urb = pTcb->urb;
+ int retval = 0;
+
+ urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len,
+ GFP_ATOMIC, &urb->transfer_dma);
+ if (!urb->transfer_buffer) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Error allocating memory\n");
+ return -ENOMEM;
+ }
+ memcpy(urb->transfer_buffer, data, len);
+ urb->transfer_buffer_length = len;
+
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending Bulk out packet\n");
+ /* For T3B,INT OUT end point will be used as bulk out end point */
+ if ((psIntfAdapter->psAdapter->chip_id == T3B) && (psIntfAdapter->bHighSpeedDevice == TRUE)) {
+ usb_fill_int_urb(urb, psIntfAdapter->udev,
+ psIntfAdapter->sBulkOut.bulk_out_pipe,
+ urb->transfer_buffer, len, write_bulk_callback, pTcb,
+ psIntfAdapter->sBulkOut.int_out_interval);
+ } else {
+ usb_fill_bulk_urb(urb, psIntfAdapter->udev,
+ psIntfAdapter->sBulkOut.bulk_out_pipe,
+ urb->transfer_buffer, len, write_bulk_callback, pTcb);
+ }
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */
+
+ if (false == psIntfAdapter->psAdapter->device_removed &&
+ false == psIntfAdapter->psAdapter->bEndPointHalted &&
+ false == psIntfAdapter->bSuspended &&
+ false == psIntfAdapter->bPreparingForBusSuspend) {
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "failed submitting write urb, error %d", retval);
+ if (retval == -EPIPE) {
+ psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
+ wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
+ }
+ }
+ }
+ return retval;
+}
+
+int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
+{
+ struct bcm_usb_tcb *pTcb = NULL;
+
+ struct bcm_interface_adapter *psIntfAdapter = arg;
+ pTcb = GetBulkOutTcb(psIntfAdapter);
+ if (pTcb == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "No URB to transmit packet, dropping packet");
+ return -EFAULT;
+ }
+ return TransmitTcb(psIntfAdapter, pTcb, data, len);
+}
+
+
diff --git a/drivers/staging/bcm/InterfaceTx.h b/drivers/staging/bcm/InterfaceTx.h
new file mode 100644
index 00000000000..273147577c1
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceTx.h
@@ -0,0 +1,7 @@
+#ifndef _INTERFACE_TX_H
+#define _INTERFACE_TX_H
+
+INT InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len);
+
+#endif
+
diff --git a/drivers/staging/bcm/Ioctl.h b/drivers/staging/bcm/Ioctl.h
new file mode 100644
index 00000000000..797f862b90c
--- /dev/null
+++ b/drivers/staging/bcm/Ioctl.h
@@ -0,0 +1,226 @@
+#ifndef _IOCTL_H_
+#define _IOCTL_H_
+
+struct bcm_rdm_buffer {
+ unsigned long Register;
+ unsigned long Length;
+} __packed;
+
+struct bcm_wrm_buffer {
+ unsigned long Register;
+ unsigned long Length;
+ unsigned char Data[4];
+} __packed;
+
+struct bcm_ioctl_buffer {
+ void __user *InputBuffer;
+ unsigned long InputLength;
+ void __user *OutputBuffer;
+ unsigned long OutputLength;
+} __packed;
+
+struct bcm_gpio_info {
+ unsigned int uiGpioNumber; /* valid numbers 0-15 */
+ unsigned int uiGpioValue; /* 1 set ; 0 not set */
+} __packed;
+
+struct bcm_user_thread_req {
+ /* 0->Inactivate LED thread. */
+ /* 1->Activate the LED thread */
+ unsigned int ThreadState;
+} __packed;
+
+#define LED_THREAD_ACTIVATION_REQ 1
+#define BCM_IOCTL 'k'
+#define IOCTL_SEND_CONTROL_MESSAGE _IOW(BCM_IOCTL, 0x801, int)
+#define IOCTL_BCM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x802, int)
+#define IOCTL_BCM_REGISTER_READ _IOR(BCM_IOCTL, 0x803, int)
+#define IOCTL_BCM_COMMON_MEMORY_WRITE _IOW(BCM_IOCTL, 0x804, int)
+#define IOCTL_BCM_COMMON_MEMORY_READ _IOR(BCM_IOCTL, 0x805, int)
+#define IOCTL_GET_CONTROL_MESSAGE _IOR(BCM_IOCTL, 0x806, int)
+#define IOCTL_BCM_FIRMWARE_DOWNLOAD _IOW(BCM_IOCTL, 0x807, int)
+#define IOCTL_BCM_SET_SEND_VCID _IOW(BCM_IOCTL, 0x808, int)
+#define IOCTL_BCM_SWITCH_TRANSFER_MODE _IOW(BCM_IOCTL, 0x809, int)
+#define IOCTL_LINK_REQ _IOW(BCM_IOCTL, 0x80A, int)
+#define IOCTL_RSSI_LEVEL_REQ _IOW(BCM_IOCTL, 0x80B, int)
+#define IOCTL_IDLE_REQ _IOW(BCM_IOCTL, 0x80C, int)
+#define IOCTL_SS_INFO_REQ _IOW(BCM_IOCTL, 0x80D, int)
+#define IOCTL_GET_STATISTICS_POINTER _IOW(BCM_IOCTL, 0x80E, int)
+#define IOCTL_CM_REQUEST _IOW(BCM_IOCTL, 0x80F, int)
+#define IOCTL_INIT_PARAM_REQ _IOW(BCM_IOCTL, 0x810, int)
+#define IOCTL_MAC_ADDR_REQ _IOW(BCM_IOCTL, 0x811, int)
+#define IOCTL_MAC_ADDR_RESP _IOWR(BCM_IOCTL, 0x812, int)
+#define IOCTL_CLASSIFICATION_RULE _IOW(BCM_IOCTL, 0x813, char)
+#define IOCTL_CLOSE_NOTIFICATION _IO(BCM_IOCTL, 0x814)
+#define IOCTL_LINK_UP _IO(BCM_IOCTL, 0x815)
+#define IOCTL_LINK_DOWN _IO(BCM_IOCTL, 0x816, struct bcm_ioctl_buffer)
+#define IOCTL_CHIP_RESET _IO(BCM_IOCTL, 0x816)
+#define IOCTL_CINR_LEVEL_REQ _IOW(BCM_IOCTL, 0x817, char)
+#define IOCTL_WTM_CONTROL_REQ _IOW(BCM_IOCTL, 0x817, char)
+#define IOCTL_BE_BUCKET_SIZE _IOW(BCM_IOCTL, 0x818, unsigned long)
+#define IOCTL_RTPS_BUCKET_SIZE _IOW(BCM_IOCTL, 0x819, unsigned long)
+#define IOCTL_QOS_THRESHOLD _IOW(BCM_IOCTL, 0x820, unsigned long)
+#define IOCTL_DUMP_PACKET_INFO _IO(BCM_IOCTL, 0x821)
+#define IOCTL_GET_PACK_INFO _IOR(BCM_IOCTL, 0x823, int)
+#define IOCTL_BCM_GET_DRIVER_VERSION _IOR(BCM_IOCTL, 0x829, int)
+#define IOCTL_BCM_GET_CURRENT_STATUS _IOW(BCM_IOCTL, 0x828, int)
+#define IOCTL_BCM_GPIO_SET_REQUEST _IOW(BCM_IOCTL, 0x82A, int)
+#define IOCTL_BCM_GPIO_STATUS_REQUEST _IOW(BCM_IOCTL, 0x82b, int)
+#define IOCTL_BCM_GET_DSX_INDICATION _IOR(BCM_IOCTL, 0x854, int)
+#define IOCTL_BCM_BUFFER_DOWNLOAD_START _IOW(BCM_IOCTL, 0x855, int)
+#define IOCTL_BCM_BUFFER_DOWNLOAD _IOW(BCM_IOCTL, 0x856, int)
+#define IOCTL_BCM_BUFFER_DOWNLOAD_STOP _IOW(BCM_IOCTL, 0x857, int)
+#define IOCTL_BCM_REGISTER_WRITE_PRIVATE _IOW(BCM_IOCTL, 0x826, char)
+#define IOCTL_BCM_REGISTER_READ_PRIVATE _IOW(BCM_IOCTL, 0x827, char)
+#define IOCTL_BCM_SET_DEBUG _IOW(BCM_IOCTL, 0x824, struct bcm_ioctl_buffer)
+#define IOCTL_BCM_EEPROM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x858, int)
+#define IOCTL_BCM_EEPROM_REGISTER_READ _IOR(BCM_IOCTL, 0x859, int)
+#define IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE _IOR(BCM_IOCTL, 0x860, int)
+#define IOCTL_BCM_SET_MAC_TRACING _IOW(BCM_IOCTL, 0x82c, int)
+#define IOCTL_BCM_GET_HOST_MIBS _IOW(BCM_IOCTL, 0x853, int)
+#define IOCTL_BCM_NVM_READ _IOR(BCM_IOCTL, 0x861, int)
+#define IOCTL_BCM_NVM_WRITE _IOW(BCM_IOCTL, 0x862, int)
+#define IOCTL_BCM_GET_NVM_SIZE _IOR(BCM_IOCTL, 0x863, int)
+#define IOCTL_BCM_CAL_INIT _IOR(BCM_IOCTL, 0x864, int)
+#define IOCTL_BCM_BULK_WRM _IOW(BCM_IOCTL, 0x90B, int)
+#define IOCTL_BCM_FLASH2X_SECTION_READ _IOR(BCM_IOCTL, 0x865, int)
+#define IOCTL_BCM_FLASH2X_SECTION_WRITE _IOW(BCM_IOCTL, 0x866, int)
+#define IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP _IOR(BCM_IOCTL, 0x867, int)
+#define IOCTL_BCM_SET_ACTIVE_SECTION _IOW(BCM_IOCTL, 0x868, int)
+#define IOCTL_BCM_IDENTIFY_ACTIVE_SECTION _IO(BCM_IOCTL, 0x869)
+#define IOCTL_BCM_COPY_SECTION _IOW(BCM_IOCTL, 0x870, int)
+#define IOCTL_BCM_GET_FLASH_CS_INFO _IOR(BCM_IOCTL, 0x871, int)
+#define IOCTL_BCM_SELECT_DSD _IOW(BCM_IOCTL, 0x872, int)
+#define IOCTL_BCM_NVM_RAW_READ _IOR(BCM_IOCTL, 0x875, int)
+#define IOCTL_BCM_CNTRLMSG_MASK _IOW(BCM_IOCTL, 0x874, int)
+#define IOCTL_BCM_GET_DEVICE_DRIVER_INFO _IOR(BCM_IOCTL, 0x877, int)
+#define IOCTL_BCM_TIME_SINCE_NET_ENTRY _IOR(BCM_IOCTL, 0x876, int)
+#define BCM_LED_THREAD_STATE_CHANGE_REQ _IOW(BCM_IOCTL, 0x878, int)
+#define IOCTL_BCM_GPIO_MULTI_REQUEST _IOW(BCM_IOCTL, 0x82D, struct bcm_ioctl_buffer)
+#define IOCTL_BCM_GPIO_MODE_REQUEST _IOW(BCM_IOCTL, 0x82E, struct bcm_ioctl_buffer)
+
+enum bcm_interface_type {
+ BCM_MII,
+ BCM_CARDBUS,
+ BCM_USB,
+ BCM_SDIO,
+ BCM_PCMCIA
+};
+
+struct bcm_driver_info {
+ enum bcm_nvm_type u32NVMType;
+ unsigned int MaxRDMBufferSize;
+ enum bcm_interface_type u32InterfaceType;
+ unsigned int u32DSDStartOffset;
+ unsigned int u32RxAlignmentCorrection;
+ unsigned int u32Reserved[10];
+};
+
+struct bcm_nvm_readwrite {
+ void __user *pBuffer;
+ uint32_t uiOffset;
+ uint32_t uiNumBytes;
+ bool bVerify;
+};
+
+struct bcm_bulk_wrm_buffer {
+ unsigned long Register;
+ unsigned long SwapEndian;
+ unsigned long Values[1];
+};
+
+enum bcm_flash2x_section_val {
+ NO_SECTION_VAL = 0, /* no section is chosen when absolute offset is given for RD/WR */
+ ISO_IMAGE1,
+ ISO_IMAGE2,
+ DSD0,
+ DSD1,
+ DSD2,
+ VSA0,
+ VSA1,
+ VSA2,
+ SCSI,
+ CONTROL_SECTION,
+ ISO_IMAGE1_PART2,
+ ISO_IMAGE1_PART3,
+ ISO_IMAGE2_PART2,
+ ISO_IMAGE2_PART3,
+ TOTAL_SECTIONS
+};
+
+/*
+ * Structure used for READ/WRITE Flash Map2.x
+ */
+struct bcm_flash2x_readwrite {
+ enum bcm_flash2x_section_val Section; /* which section has to be read/written */
+ u32 offset; /* Offset within Section. */
+ u32 numOfBytes; /* NOB from the offset */
+ u32 bVerify;
+ void __user *pDataBuff; /* Buffer for reading/writing */
+};
+
+/*
+ * This structure is used for coping one section to other.
+ * there are two ways to copy one section to other.
+ * it NOB =0, complete section will be copied on to other.
+ * if NOB !=0, only NOB will be copied from the given offset.
+ */
+
+struct bcm_flash2x_copy_section {
+ enum bcm_flash2x_section_val SrcSection;
+ enum bcm_flash2x_section_val DstSection;
+ u32 offset;
+ u32 numOfBytes;
+};
+
+/*
+ * This section provide the complete bitmap of the Flash.
+ * using this map lib/APP will issue read/write command.
+ * Fields are defined as :
+ * Bit [0] = section is present //1:present, 0: Not present
+ * Bit [1] = section is valid //1: valid, 0: not valid
+ * Bit [2] = Section is R/W //0: RW, 1: RO
+ * Bit [3] = Section is Active or not 1 means Active, 0->inactive
+ * Bit [7...3] = Reserved
+ */
+
+struct bcm_flash2x_bitmap {
+ unsigned char ISO_IMAGE1;
+ unsigned char ISO_IMAGE2;
+ unsigned char DSD0;
+ unsigned char DSD1;
+ unsigned char DSD2;
+ unsigned char VSA0;
+ unsigned char VSA1;
+ unsigned char VSA2;
+ unsigned char SCSI;
+ unsigned char CONTROL_SECTION;
+ /* Reserved for future use */
+ unsigned char Reserved0;
+ unsigned char Reserved1;
+ unsigned char Reserved2;
+};
+
+struct bcm_time_elapsed {
+ u64 ul64TimeElapsedSinceNetEntry;
+ u32 uiReserved[4];
+};
+
+enum {
+ WIMAX_IDX = 0, /* To access WiMAX chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE */
+ HOST_IDX, /* To access Host chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE */
+ MAX_IDX
+};
+
+struct bcm_gpio_multi_info {
+ unsigned int uiGPIOCommand; /* 1 for set and 0 for get */
+ unsigned int uiGPIOMask; /* set the correspondig bit to 1 to access GPIO */
+ unsigned int uiGPIOValue; /* 0 or 1; value to be set when command is 1. */
+} __packed;
+
+struct bcm_gpio_multi_mode {
+ unsigned int uiGPIOMode; /* 1 for OUT mode, 0 for IN mode */
+ unsigned int uiGPIOMask; /* GPIO mask to set mode */
+} __packed;
+
+#endif
diff --git a/drivers/staging/bcm/Kconfig b/drivers/staging/bcm/Kconfig
new file mode 100644
index 00000000000..8acf4b24a7c
--- /dev/null
+++ b/drivers/staging/bcm/Kconfig
@@ -0,0 +1,6 @@
+config BCM_WIMAX
+ tristate "Beceem BCS200/BCS220-3 and BCSM250 wimax support"
+ depends on USB && NET
+ help
+ This is an experimental driver for the Beceem WIMAX chipset used
+ by Sprint 4G.
diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c
new file mode 100644
index 00000000000..f95b06713a2
--- /dev/null
+++ b/drivers/staging/bcm/LeakyBucket.c
@@ -0,0 +1,317 @@
+/**********************************************************************
+* LEAKYBUCKET.C
+* This file contains the routines related to Leaky Bucket Algorithm.
+***********************************************************************/
+#include "headers.h"
+
+/*********************************************************************
+* Function - UpdateTokenCount()
+*
+* Description - This function calculates the token count for each
+* channel and updates the same in Adapter strucuture.
+*
+* Parameters - Adapter: Pointer to the Adapter structure.
+*
+* Returns - None
+**********************************************************************/
+
+static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
+{
+ ULONG liCurrentTime;
+ INT i = 0;
+ struct timeval tv;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+ "=====>\n");
+ if (NULL == Adapter) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
+ DBG_LVL_ALL, "Adapter found NULL!\n");
+ return;
+ }
+
+ do_gettimeofday(&tv);
+ for (i = 0; i < NO_OF_QUEUES; i++) {
+ if (TRUE == Adapter->PackInfo[i].bValid &&
+ (1 == Adapter->PackInfo[i].ucDirection)) {
+ liCurrentTime = ((tv.tv_sec-
+ Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
+ (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
+ 1000);
+ if (0 != liCurrentTime) {
+ Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG)
+ ((Adapter->PackInfo[i].uiMaxAllowedRate) *
+ ((ULONG)((liCurrentTime)))/1000);
+ memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt,
+ &tv, sizeof(struct timeval));
+ Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime;
+ if (Adapter->PackInfo[i].uiCurrentTokenCount >=
+ Adapter->PackInfo[i].uiMaxBucketSize) {
+ Adapter->PackInfo[i].uiCurrentTokenCount =
+ Adapter->PackInfo[i].uiMaxBucketSize;
+ }
+ }
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
+ return;
+
+}
+
+
+/*********************************************************************
+* Function - IsPacketAllowedForFlow()
+*
+* Description - This function checks whether the given packet from the
+* specified queue can be allowed for transmission by
+* checking the token count.
+*
+* Parameters - Adapter : Pointer to the Adpater structure.
+* - iQIndex : The queue Identifier.
+* - ulPacketLength: Number of bytes to be transmitted.
+*
+* Returns - The number of bytes allowed for transmission.
+*
+***********************************************************************/
+static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
+{
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
+ /* Validate the parameters */
+ if (NULL == Adapter || (psSF < Adapter->PackInfo &&
+ (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo));
+ return 0;
+ }
+
+ if (false != psSF->bValid && psSF->ucDirection) {
+ if (0 != psSF->uiCurrentTokenCount) {
+ return psSF->uiCurrentTokenCount;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
+ psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
+ psSF->uiPendedLast = 1;
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
+ return 0;
+}
+
+/**
+@ingroup tx_functions
+This function despatches packet from the specified queue.
+@return Zero(success) or Negative value(failure)
+*/
+static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
+ struct bcm_packet_info *psSF, /**<Queue identifier*/
+ struct sk_buff *Packet) /**<Pointer to the packet to be sent*/
+{
+ INT Status = STATUS_FAILURE;
+ UINT uiIndex = 0, PktLen = 0;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
+ if (!Adapter || !Packet || !psSF) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
+ return -EINVAL;
+ }
+
+ if (psSF->liDrainCalculated == 0)
+ psSF->liDrainCalculated = jiffies;
+ /* send the packet to the fifo.. */
+ PktLen = Packet->len;
+ Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
+ if (Status == 0) {
+ for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
+ if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
+ Adapter->aTxPktSizeHist[uiIndex]++;
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
+ return Status;
+}
+
+/************************************************************************
+* Function - CheckAndSendPacketFromIndex()
+*
+* Description - This function dequeues the data/control packet from the
+* specified queue for transmission.
+*
+* Parameters - Adapter : Pointer to the driver control structure.
+* - iQIndex : The queue Identifier.
+*
+* Returns - None.
+*
+****************************************************************************/
+static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
+{
+ struct sk_buff *QueuePacket = NULL;
+ char *pControlPacket = NULL;
+ INT Status = 0;
+ int iPacketLen = 0;
+
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
+ if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
+ if (!psSF->ucDirection)
+ return;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
+ if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
+ return; /* in idle mode */
+
+ /* Check for Free Descriptors */
+ if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc));
+ return;
+ }
+
+ spin_lock_bh(&psSF->SFQueueLock);
+ QueuePacket = psSF->FirstTxQueue;
+
+ if (QueuePacket) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
+
+ if (psSF->bEthCSSupport)
+ iPacketLen = QueuePacket->len;
+ else
+ iPacketLen = QueuePacket->len-ETH_HLEN;
+
+ iPacketLen <<= 3;
+ if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
+ (iPacketLen >> 3));
+
+ DEQUEUEPACKET(psSF->FirstTxQueue, psSF->LastTxQueue);
+ psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
+ psSF->uiCurrentPacketsOnHost--;
+ atomic_dec(&Adapter->TotalPacketCount);
+ spin_unlock_bh(&psSF->SFQueueLock);
+
+ Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
+ psSF->uiPendedLast = false;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
+ psSF->uiCurrentTokenCount, iPacketLen);
+ /*
+ this part indicates that because of non-availability of the tokens
+ pkt has not been send out hence setting the pending flag indicating the host to send it out
+ first next iteration.
+ */
+ psSF->uiPendedLast = TRUE;
+ spin_unlock_bh(&psSF->SFQueueLock);
+ }
+ } else {
+ spin_unlock_bh(&psSF->SFQueueLock);
+ }
+ } else {
+
+ if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) &&
+ (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
+ atomic_read(&Adapter->index_wr_txcntrlpkt))) {
+ pControlPacket = Adapter->txctlpacket
+ [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
+ if (pControlPacket) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
+ Status = SendControlPacket(Adapter, pControlPacket);
+ if (STATUS_SUCCESS == Status) {
+ spin_lock_bh(&psSF->SFQueueLock);
+ psSF->NumOfPacketsSent++;
+ psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength;
+ psSF->uiSentPackets++;
+ atomic_dec(&Adapter->TotalPacketCount);
+ psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength;
+ psSF->uiCurrentPacketsOnHost--;
+ atomic_inc(&Adapter->index_rd_txcntrlpkt);
+ spin_unlock_bh(&psSF->SFQueueLock);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+* Function - transmit_packets()
+*
+* Description - This function transmits the packets from different
+* queues, if free descriptors are available on target.
+*
+* Parameters - Adapter: Pointer to the Adapter structure.
+*
+* Returns - None.
+********************************************************************/
+VOID transmit_packets(struct bcm_mini_adapter *Adapter)
+{
+ UINT uiPrevTotalCount = 0;
+ int iIndex = 0;
+
+ bool exit_flag = TRUE;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
+
+ if (NULL == Adapter) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
+ return;
+ }
+ if (Adapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
+ return;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
+
+ UpdateTokenCount(Adapter);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
+
+ PruneQueueAllSF(Adapter);
+
+ uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
+
+ for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
+ if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
+ break;
+
+ if (Adapter->PackInfo[iIndex].bValid &&
+ Adapter->PackInfo[iIndex].uiPendedLast &&
+ Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+ CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
+ uiPrevTotalCount--;
+ }
+ }
+
+ while (uiPrevTotalCount > 0 && !Adapter->device_removed) {
+ exit_flag = TRUE;
+ /* second iteration to parse non-pending queues */
+ for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
+ if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
+ break;
+
+ if (Adapter->PackInfo[iIndex].bValid &&
+ Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
+ !Adapter->PackInfo[iIndex].uiPendedLast) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+ CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
+ uiPrevTotalCount--;
+ exit_flag = false;
+ }
+ }
+
+ if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
+ break;
+ }
+ if (exit_flag == TRUE)
+ break;
+ } /* end of inner while loop */
+
+ update_per_cid_rx(Adapter);
+ Adapter->txtransmit_running = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
+}
diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h
new file mode 100644
index 00000000000..dc01e3016d4
--- /dev/null
+++ b/drivers/staging/bcm/Macros.h
@@ -0,0 +1,352 @@
+/*************************************
+* Macros.h
+**************************************/
+#ifndef __MACROS_H__
+#define __MACROS_H__
+
+#define TX_TIMER_PERIOD 10 /*10 msec*/
+#define MAX_CLASSIFIERS 100
+#define MAX_TARGET_DSX_BUFFERS 24
+
+#define MAX_CNTRL_PKTS 100
+#define MAX_DATA_PKTS 200
+#define MAX_ETH_SIZE 1536
+#define MAX_CNTL_PKT_SIZE 2048
+
+#define MTU_SIZE 1400
+#define TX_QLEN 5
+
+#define MAC_ADDR_REGISTER 0xbf60d000
+
+
+/* Quality of Service */
+#define NO_OF_QUEUES 17
+#define HiPriority (NO_OF_QUEUES-1)
+#define LowPriority 0
+#define BE 2
+#define rtPS 4
+#define ERTPS 5
+#define UGS 6
+
+#define BE_BUCKET_SIZE (1024*1024*100) /* 32kb */
+#define rtPS_BUCKET_SIZE (1024*1024*100) /* 8kb */
+#define MAX_ALLOWED_RATE (1024*1024*100)
+#define TX_PACKET_THRESHOLD 10
+#define XSECONDS (1*HZ)
+#define DSC_ACTIVATE_REQUEST 248
+#define QUEUE_DEPTH_OFFSET 0x1fc01000
+#define MAX_DEVICE_DESC_SIZE 2040
+#define MAX_CTRL_QUEUE_LEN 100
+#define MAX_APP_QUEUE_LEN 200
+#define MAX_LATENCY_ALLOWED 0xFFFFFFFF
+#define DEFAULT_UG_INTERVAL 250
+#define DEFAULT_UGI_FACTOR 4
+
+#define DEFAULT_PERSFCOUNT 60
+#define MAX_CONNECTIONS 10
+#define MAX_CLASS_NAME_LENGTH 32
+
+#define ETH_LENGTH_OF_ADDRESS 6
+#define MAX_MULTICAST_ADDRESSES 32
+#define IP_LENGTH_OF_ADDRESS 4
+
+#define IP_PACKET_ONLY_MODE 0
+#define ETH_PACKET_TUNNELING_MODE 1
+
+/* Link Request */
+#define SET_MAC_ADDRESS_REQUEST 0
+#define SYNC_UP_REQUEST 1
+#define SYNCED_UP 2
+#define LINK_UP_REQUEST 3
+#define LINK_CONNECTED 4
+#define SYNC_UP_NOTIFICATION 2
+#define LINK_UP_NOTIFICATION 4
+
+
+#define LINK_NET_ENTRY 0x0002
+#define HMC_STATUS 0x0004
+#define LINK_UP_CONTROL_REQ 0x83
+
+#define STATS_POINTER_REQ_STATUS 0x86
+#define NETWORK_ENTRY_REQ_PAYLOAD 198
+#define LINK_DOWN_REQ_PAYLOAD 226
+#define SYNC_UP_REQ_PAYLOAD 228
+#define STATISTICS_POINTER_REQ 237
+#define LINK_UP_REQ_PAYLOAD 245
+#define LINK_UP_ACK 246
+
+#define STATS_MSG_SIZE 4
+#define INDEX_TO_DATA 4
+
+#define GO_TO_IDLE_MODE_PAYLOAD 210
+#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211
+#define IDLE_MODE_SF_UPDATE_MSG 187
+
+#define SKB_RESERVE_ETHERNET_HEADER 16
+#define SKB_RESERVE_PHS_BYTES 32
+
+#define IP_PACKET_ONLY_MODE 0
+#define ETH_PACKET_TUNNELING_MODE 1
+
+#define ETH_CS_802_3 1
+#define ETH_CS_802_1Q_VLAN 3
+#define IPV4_CS 1
+#define IPV6_CS 2
+#define ETH_CS_MASK 0x3f
+
+/** \brief Validity bit maps for TLVs in packet classification rule */
+
+#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0
+#define PKT_CLASSIFICATION_VLANID_VALID 1
+
+#ifndef MIN
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+
+/*Leader related terms */
+#define LEADER_STATUS 0x00
+#define LEADER_STATUS_TCP_ACK 0x1
+#define LEADER_SIZE sizeof(struct bcm_leader)
+#define MAC_ADDR_REQ_SIZE sizeof(struct bcm_packettosend)
+#define SS_INFO_REQ_SIZE sizeof(struct bcm_packettosend)
+#define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest))
+#define IDLE_REQ_SIZE sizeof(struct bcm_packettosend)
+
+
+#define MAX_TRANSFER_CTRL_BYTE_USB (2*1024)
+
+#define GET_MAILBOX1_REG_REQUEST 0x87
+#define GET_MAILBOX1_REG_RESPONSE 0x67
+#define VCID_CONTROL_PACKET 0x00
+
+#define TRANSMIT_NETWORK_DATA 0x00
+#define RECEIVED_NETWORK_DATA 0x20
+
+#define CM_RESPONSES 0xA0
+#define STATUS_RSP 0xA1
+#define LINK_CONTROL_RESP 0xA2
+#define IDLE_MODE_STATUS 0xA3
+#define STATS_POINTER_RESP 0xA6
+#define MGMT_MSG_INFO_SW_STATUS 0xA7
+#define AUTH_SS_HOST_MSG 0xA8
+
+#define CM_DSA_ACK_PAYLOAD 247
+#define CM_DSC_ACK_PAYLOAD 248
+#define CM_DSD_ACK_PAYLOAD 249
+#define CM_DSDEACTVATE 250
+#define TOTAL_MASKED_ADDRESS_IN_BYTES 32
+
+#define MAC_REQ 0
+#define LINK_RESP 1
+#define RSSI_INDICATION 2
+
+#define SS_INFO 4
+#define STATISTICS_INFO 5
+#define CM_INDICATION 6
+#define PARAM_RESP 7
+#define BUFFER_1K 1024
+#define BUFFER_2K (BUFFER_1K*2)
+#define BUFFER_4K (BUFFER_2K*2)
+#define BUFFER_8K (BUFFER_4K*2)
+#define BUFFER_16K (BUFFER_8K*2)
+#define DOWNLINK_DIR 0
+#define UPLINK_DIR 1
+
+#define BCM_SIGNATURE "BECEEM"
+
+
+#define GPIO_OUTPUT_REGISTER 0x0F00003C
+#define BCM_GPIO_OUTPUT_SET_REG 0x0F000040
+#define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044
+#define GPIO_MODE_REGISTER 0x0F000034
+#define GPIO_PIN_STATE_REGISTER 0x0F000038
+
+struct bcm_link_state {
+ unsigned char ucLinkStatus;
+ unsigned char bIdleMode;
+ unsigned char bShutdownMode;
+};
+
+enum enLinkStatus {
+ WAIT_FOR_SYNC = 1,
+ PHY_SYNC_ACHIVED = 2,
+ LINKUP_IN_PROGRESS = 3,
+ LINKUP_DONE = 4,
+ DREG_RECEIVED = 5,
+ LINK_STATUS_RESET_RECEIVED = 6,
+ PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7,
+ LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8,
+ COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW = 9
+};
+
+enum bcm_phs_dsc_action {
+ eAddPHSRule = 0,
+ eSetPHSRule,
+ eDeletePHSRule,
+ eDeleteAllPHSRules
+};
+
+#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 /* Host to Mac */
+#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 /* Mac to Host */
+#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 /* 0b000010000 */
+#define MINIMUM_PENDING_DESCRIPTORS 5
+
+#define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC
+#define SHUTDOWN_ACK_FROM_DRIVER 0x1
+#define SHUTDOWN_NACK_FROM_DRIVER 0x2
+
+#define LINK_SYNC_UP_SUBTYPE 0x0001
+#define LINK_SYNC_DOWN_SUBTYPE 0x0001
+
+
+
+#define CONT_MODE 1
+#define SINGLE_DESCRIPTOR 1
+
+
+#define DESCRIPTOR_LENGTH 0x30
+#define FIRMWARE_DESCS_ADDRESS 0x1F100000
+
+
+#define CLOCK_RESET_CNTRL_REG_1 0x0F00000C
+#define CLOCK_RESET_CNTRL_REG_2 0x0F000840
+
+
+
+#define TX_DESCRIPTOR_HEAD_REGISTER 0x0F010034
+#define RX_DESCRIPTOR_HEAD_REGISTER 0x0F010094
+
+#define STATISTICS_BEGIN_ADDR 0xbf60f02c
+
+#define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10)
+
+#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN)
+#define AUTO_LINKUP_ENABLE 0x2
+#define AUTO_SYNC_DISABLE 0x1
+#define AUTO_FIRM_DOWNLOAD 0x1
+#define SETTLE_DOWN_TIME 50
+
+#define HOST_BUS_SUSPEND_BIT 16
+
+#define IDLE_MESSAGE 0x81
+
+#define MIPS_CLOCK_133MHz 1
+
+#define TARGET_CAN_GO_TO_IDLE_MODE 2
+#define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3
+#define IDLE_MODE_PAYLOAD_LENGTH 8
+
+#define IP_HEADER(Buffer) ((IPHeaderFormat *)(Buffer))
+#define IPV4 4
+#define IP_VERSION(byte) (((byte&0xF0)>>4))
+
+#define SET_MAC_ADDRESS 193
+#define SET_MAC_ADDRESS_RESPONSE 236
+
+#define IDLE_MODE_WAKEUP_PATTERN 0xd0ea1d1e
+#define IDLE_MODE_WAKEUP_NOTIFIER_ADDRESS 0x1FC02FA8
+#define IDLE_MODE_MAX_RETRY_COUNT 1000
+
+#define CONFIG_BEGIN_ADDR 0xBF60B000
+
+#define FIRMWARE_BEGIN_ADDR 0xBFC00000
+
+#define INVALID_QUEUE_INDEX NO_OF_QUEUES
+
+#define INVALID_PID ((pid_t)-1)
+#define DDR_80_MHZ 0
+#define DDR_100_MHZ 1
+#define DDR_120_MHZ 2 /* Additional Frequency for T3LP */
+#define DDR_133_MHZ 3
+#define DDR_140_MHZ 4 /* Not Used (Reserved for future) */
+#define DDR_160_MHZ 5 /* Additional Frequency for T3LP */
+#define DDR_180_MHZ 6 /* Not Used (Reserved for future) */
+#define DDR_200_MHZ 7 /* Not Used (Reserved for future) */
+
+#define MIPS_200_MHZ 0
+#define MIPS_160_MHZ 1
+
+#define PLL_800_MHZ 0
+#define PLL_266_MHZ 1
+
+#define DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING 0
+#define DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING 1
+#define DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN 2
+#define DEVICE_POWERSAVE_MODE_AS_RESERVED 3
+#define DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE 4
+
+
+#define EEPROM_REJECT_REG_1 0x0f003018
+#define EEPROM_REJECT_REG_2 0x0f00301c
+#define EEPROM_REJECT_REG_3 0x0f003008
+#define EEPROM_REJECT_REG_4 0x0f003020
+#define EEPROM_REJECT_MASK 0x0fffffff
+#define VSG_MODE 0x3
+
+/* Idle Mode Related Registers */
+#define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C
+#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC
+
+#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e
+#define DEVICE_INT_OUT_EP_REG0 0x0F011870
+#define DEVICE_INT_OUT_EP_REG1 0x0F011874
+
+#define BIN_FILE "/lib/firmware/macxvi200.bin"
+#define CFG_FILE "/lib/firmware/macxvi.cfg"
+#define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128
+#define MIN_VAL(x, y) ((x) < (y) ? (x) : (y))
+#define MAC_ADDRESS_SIZE 6
+#define EEPROM_COMMAND_Q_REG 0x0F003018
+#define EEPROM_READ_DATA_Q_REG 0x0F003020
+#define CHIP_ID_REG 0x0F000000
+#define GPIO_MODE_REG 0x0F000034
+#define GPIO_OUTPUT_REG 0x0F00003C
+#define WIMAX_MAX_ALLOWED_RATE (1024*1024*50)
+
+#define T3 0xbece0300
+#define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400
+
+#define RWM_READ 0
+#define RWM_WRITE 1
+
+#define T3LPB 0xbece3300
+#define BCS220_2 0xbece3311
+#define BCS220_2BC 0xBECE3310
+#define BCS250_BC 0xbece3301
+#define BCS220_3 0xbece3321
+
+
+#define HPM_CONFIG_LDO145 0x0F000D54
+#define HPM_CONFIG_MSW 0x0F000D58
+
+#define T3B 0xbece0310
+enum bcm_nvm_type {
+ NVM_AUTODETECT = 0,
+ NVM_EEPROM,
+ NVM_FLASH,
+ NVM_UNKNOWN
+};
+
+enum bcm_pmu_modes {
+ HYBRID_MODE_7C = 0,
+ INTERNAL_MODE_6 = 1,
+ HYBRID_MODE_6 = 2
+};
+
+#define MAX_RDM_WRM_RETIRES 1
+
+enum eAbortPattern {
+ ABORT_SHUTDOWN_MODE = 1,
+ ABORT_IDLE_REG = 1,
+ ABORT_IDLE_MODE = 2,
+ ABORT_IDLE_SYNCDOWN = 3
+};
+
+
+/* Offsets used by driver in skb cb variable */
+#define SKB_CB_CLASSIFICATION_OFFSET 0
+#define SKB_CB_LATENCY_OFFSET 1
+#define SKB_CB_TCPACK_OFFSET 2
+
+#endif /* __MACROS_H__ */
diff --git a/drivers/staging/bcm/Makefile b/drivers/staging/bcm/Makefile
new file mode 100644
index 00000000000..652b7f87737
--- /dev/null
+++ b/drivers/staging/bcm/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for Beceem USB Wimax card
+#
+
+obj-$(CONFIG_BCM_WIMAX) += bcm_wimax.o
+
+bcm_wimax-y := InterfaceDld.o InterfaceIdleMode.o InterfaceInit.o InterfaceRx.o \
+ InterfaceIsr.o InterfaceMisc.o InterfaceTx.o \
+ CmHost.o IPv6Protocol.o Qos.o Transmit.o\
+ Bcmnet.o DDRInit.o HandleControlPacket.o\
+ LeakyBucket.o Misc.o sort.o Bcmchar.o hostmibs.o PHSModule.o\
+ led_control.o nvm.o vendorspecificextn.o
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
new file mode 100644
index 00000000000..7b2fa0f4a2e
--- /dev/null
+++ b/drivers/staging/bcm/Misc.c
@@ -0,0 +1,1580 @@
+#include "headers.h"
+
+static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, unsigned int loc);
+static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter);
+static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer);
+static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter);
+static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter);
+
+static void default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiLoopIndex;
+
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) {
+ Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD;
+ Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate = MAX_ALLOWED_RATE;
+ Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize = 20*1024*1024;
+ }
+
+ Adapter->BEBucketSize = BE_BUCKET_SIZE;
+ Adapter->rtPSBucketSize = rtPS_BUCKET_SIZE;
+ Adapter->LinkStatus = SYNC_UP_REQUEST;
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
+ Adapter->usBestEffortQueueIndex = -1;
+ return;
+}
+
+int InitAdapter(struct bcm_mini_adapter *psAdapter)
+{
+ int i = 0;
+ int Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
+
+ if (psAdapter == NULL) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL");
+ return -EINVAL;
+ }
+
+ sema_init(&psAdapter->NVMRdmWrmLock, 1);
+ sema_init(&psAdapter->rdmwrmsync, 1);
+ spin_lock_init(&psAdapter->control_queue_lock);
+ spin_lock_init(&psAdapter->txtransmitlock);
+ sema_init(&psAdapter->RxAppControlQueuelock, 1);
+ sema_init(&psAdapter->fw_download_sema, 1);
+ sema_init(&psAdapter->LowPowerModeSync, 1);
+
+ for (i = 0; i < NO_OF_QUEUES; i++)
+ spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock);
+ i = 0;
+
+ init_waitqueue_head(&psAdapter->process_rx_cntrlpkt);
+ init_waitqueue_head(&psAdapter->tx_packet_wait_queue);
+ init_waitqueue_head(&psAdapter->process_read_wait_queue);
+ init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue);
+ init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue);
+ psAdapter->waiting_to_fw_download_done = TRUE;
+ psAdapter->fw_download_done = false;
+
+ default_wimax_protocol_initialize(psAdapter);
+ for (i = 0; i < MAX_CNTRL_PKTS; i++) {
+ psAdapter->txctlpacket[i] = kmalloc(MAX_CNTL_PKT_SIZE, GFP_KERNEL);
+ if (!psAdapter->txctlpacket[i]) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i);
+ return -ENOMEM;
+ }
+ }
+
+ if (AllocAdapterDsxBuffer(psAdapter)) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers");
+ return -EINVAL;
+ }
+
+ /* Initialize PHS interface */
+ if (phs_init(&psAdapter->stBCMPhsContext, psAdapter) != 0) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ Status = BcmAllocFlashCSStructure(psAdapter);
+ if (Status) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Memory Allocation for Flash structure failed");
+ return Status;
+ }
+
+ Status = vendorextnInit(psAdapter);
+
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Vendor Init Failed");
+ return Status;
+ }
+
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised");
+
+ return STATUS_SUCCESS;
+}
+
+void AdapterFree(struct bcm_mini_adapter *Adapter)
+{
+ int count;
+ beceem_protocol_reset(Adapter);
+ vendorextnExit(Adapter);
+
+ if (Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler))
+ kthread_stop(Adapter->control_packet_handler);
+
+ if (Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread))
+ kthread_stop(Adapter->transmit_packet_thread);
+
+ wake_up(&Adapter->process_read_wait_queue);
+
+ if (Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY))
+ kthread_stop(Adapter->LEDInfo.led_cntrl_threadid);
+
+ unregister_networkdev(Adapter);
+
+ /* FIXME: use proper wait_event and refcounting */
+ while (atomic_read(&Adapter->ApplicationRunning)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n", atomic_read(&Adapter->ApplicationRunning));
+ msleep(100);
+ }
+ unregister_control_device_interface(Adapter);
+ kfree(Adapter->pstargetparams);
+
+ for (count = 0; count < MAX_CNTRL_PKTS; count++)
+ kfree(Adapter->txctlpacket[count]);
+
+ FreeAdapterDsxBuffer(Adapter);
+ kfree(Adapter->pvInterfaceAdapter);
+
+ /* Free the PHS Interface */
+ PhsCleanup(&Adapter->stBCMPhsContext);
+
+ BcmDeAllocFlashCSStructure(Adapter);
+
+ free_netdev(Adapter->dev);
+}
+
+static int create_worker_threads(struct bcm_mini_adapter *psAdapter)
+{
+ /* Rx Control Packets Processing */
+ psAdapter->control_packet_handler = kthread_run((int (*)(void *))
+ control_packet_handler, psAdapter, "%s-rx", DRV_NAME);
+ if (IS_ERR(psAdapter->control_packet_handler)) {
+ pr_notice(DRV_NAME ": could not create control thread\n");
+ return PTR_ERR(psAdapter->control_packet_handler);
+ }
+
+ /* Tx Thread */
+ psAdapter->transmit_packet_thread = kthread_run((int (*)(void *))
+ tx_pkt_handler, psAdapter, "%s-tx", DRV_NAME);
+ if (IS_ERR(psAdapter->transmit_packet_thread)) {
+ pr_notice(DRV_NAME ": could not creat transmit thread\n");
+ kthread_stop(psAdapter->control_packet_handler);
+ return PTR_ERR(psAdapter->transmit_packet_thread);
+ }
+ return 0;
+}
+
+static struct file *open_firmware_file(struct bcm_mini_adapter *Adapter, const char *path)
+{
+ struct file *flp = filp_open(path, O_RDONLY, S_IRWXU);
+ if (IS_ERR(flp)) {
+ pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp));
+ flp = NULL;
+ }
+
+ if (Adapter->device_removed)
+ flp = NULL;
+
+ return flp;
+}
+
+/* Arguments:
+ * Logical Adapter
+ * Path to image file
+ * Download Address on the chip
+ */
+static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, unsigned int loc)
+{
+ int errorno = 0;
+ struct file *flp = NULL;
+ struct timeval tv = {0};
+
+ flp = open_firmware_file(Adapter, path);
+ if (!flp) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path);
+ return -ENOENT;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)file_inode(flp)->i_size, loc);
+ do_gettimeofday(&tv);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)));
+ if (Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error %x!!!", -EIO);
+ errorno = -EIO;
+ goto exit_download;
+ }
+ vfs_llseek(flp, 0, 0);
+ if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!");
+ errorno = -EIO;
+ goto exit_download;
+ }
+
+exit_download:
+ filp_close(flp, NULL);
+ return errorno;
+}
+
+/**
+ * @ingroup ctrl_pkt_functions
+ * This function copies the contents of given buffer
+ * to the control packet and queues it for transmission.
+ * @note Do not acquire the spinlock, as it it already acquired.
+ * @return SUCCESS/FAILURE.
+ * Arguments:
+ * Logical Adapter
+ * Control Packet Buffer
+ */
+int CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, void *ioBuffer)
+{
+ struct bcm_leader *pLeader = NULL;
+ int Status = 0;
+ unsigned char *ctrl_buff;
+ unsigned int pktlen = 0;
+ struct bcm_link_request *pLinkReq = NULL;
+ PUCHAR pucAddIndication = NULL;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>");
+ if (!ioBuffer) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got Null Buffer\n");
+ return -EINVAL;
+ }
+
+ pLinkReq = (struct bcm_link_request *)ioBuffer;
+ pLeader = (struct bcm_leader *)ioBuffer; /* ioBuffer Contains sw_Status and Payload */
+
+ if (Adapter->bShutStatus == TRUE &&
+ pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD &&
+ pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE) {
+
+ /* Got sync down in SHUTDOWN..we could not process this. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n");
+ return STATUS_FAILURE;
+ }
+
+ if ((pLeader->Status == LINK_UP_CONTROL_REQ) &&
+ ((pLinkReq->szData[0] == LINK_UP_REQ_PAYLOAD &&
+ (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) || /* Sync Up Command */
+ pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) /* Net Entry Command */ {
+
+ if (Adapter->LinkStatus > PHY_SYNC_ACHIVED) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "LinkStatus is Greater than PHY_SYN_ACHIEVED");
+ return STATUS_FAILURE;
+ }
+
+ if (Adapter->bShutStatus == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
+ if (Adapter->bTriedToWakeUpFromlowPowerMode == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n");
+ Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; /* change it to 1 for current support. */
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->bShutStatus, (5 * HZ));
+
+ if (Status == -ERESTARTSYS)
+ return Status;
+
+ if (Adapter->bShutStatus) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n");
+ return STATUS_FAILURE;
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Wakeup has been tried already...\n");
+ }
+ }
+ }
+
+ if (Adapter->IdleMode == TRUE) {
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */
+ if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
+ pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) {
+
+ if ((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD)) {
+ if ((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Link Down Sent in Idle Mode\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN; /* LINK DOWN sent in Idle Mode */
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_REG;
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ }
+
+ /*Setting bIdleMode_tx_from_host to TRUE to indicate LED control thread to represent
+ * the wake up from idlemode is from host
+ */
+ /* Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE; */
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+
+ /* We should not send DREG message down while in idlemode. */
+ if (LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0])
+ return STATUS_SUCCESS;
+
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->IdleMode, (5 * HZ));
+
+ if (Status == -ERESTARTSYS)
+ return Status;
+
+ if (Adapter->IdleMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n");
+ return STATUS_FAILURE;
+ }
+ } else {
+ return STATUS_SUCCESS;
+ }
+ }
+
+ /* The Driver has to send control messages with a particular VCID */
+ pLeader->Vcid = VCID_CONTROL_PACKET; /* VCID for control packet. */
+
+ /* Allocate skb for Control Packet */
+ pktlen = pLeader->PLength;
+ ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS];
+
+ if (!ctrl_buff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
+ return -ENOMEM;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
+ atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
+
+ if (pLeader) {
+ if ((pLeader->Status == 0x80) ||
+ (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
+ /*
+ * Restructure the DSX message to handle Multiple classifier Support
+ * Write the Service Flow param Structures directly to the target
+ * and embed the pointers in the DSX messages sent to target.
+ */
+ /* Lets store the current length of the control packet we are transmitting */
+ pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
+ pktlen = pLeader->PLength;
+ Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
+ if (Status != 1) {
+ ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication_alt *)pucAddIndication)->u16TID, false);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
+ return STATUS_FAILURE;
+ }
+ /*
+ * update the leader to use the new length
+ * The length of the control packet is length of message being sent + Leader length
+ */
+ pLeader->PLength = pktlen;
+ }
+ }
+
+ if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
+ return -EINVAL;
+
+ memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
+ *(struct bcm_leader *)ctrl_buff = *pLeader;
+ memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
+
+ /* Update the statistics counters */
+ spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
+ Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
+ Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
+ atomic_inc(&Adapter->TotalPacketCount);
+ spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
+ Adapter->PackInfo[HiPriority].bValid = TRUE;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
+ Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
+ Adapter->PackInfo[HiPriority].bValid);
+ Status = STATUS_SUCCESS;
+ /*Queue the packet for transmission */
+ atomic_inc(&Adapter->index_wr_txcntrlpkt);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
+ atomic_set(&Adapter->TxPktAvail, 1);
+ wake_up(&Adapter->tx_packet_wait_queue);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
+ return Status;
+}
+
+/******************************************************************
+* Function - LinkMessage()
+*
+* Description - This function builds the Sync-up and Link-up request
+* packet messages depending on the device Link status.
+*
+* Parameters - Adapter: Pointer to the Adapter structure.
+*
+* Returns - None.
+*******************************************************************/
+void LinkMessage(struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_link_request *pstLinkRequest = NULL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
+ if (Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) {
+ pstLinkRequest = kzalloc(sizeof(struct bcm_link_request), GFP_ATOMIC);
+ if (!pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
+ return;
+ }
+ /* sync up request... */
+ Adapter->LinkStatus = WAIT_FOR_SYNC; /* current link status */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
+ pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD;
+ pstLinkRequest->szData[1] = LINK_SYNC_UP_SUBTYPE;
+ pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ;
+ pstLinkRequest->Leader.PLength = sizeof(ULONG);
+ Adapter->bSyncUpRequestSent = TRUE;
+
+ } else if (Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) {
+ pstLinkRequest = kzalloc(sizeof(struct bcm_link_request), GFP_ATOMIC);
+ if (!pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
+ return;
+ }
+ /* LINK_UP_REQUEST */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
+ pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD;
+ pstLinkRequest->szData[1] = LINK_NET_ENTRY;
+ pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ;
+ pstLinkRequest->Leader.PLength = sizeof(ULONG);
+ }
+ if (pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket");
+ CopyBufferToControlPacket(Adapter, pstLinkRequest);
+ kfree(pstLinkRequest);
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <=====");
+ return;
+}
+
+/**********************************************************************
+* Function - StatisticsResponse()
+*
+* Description - This function handles the Statistics response packet.
+*
+* Parameters - Adapter : Pointer to the Adapter structure.
+* - pvBuffer: Starting address of Statistic response data.
+*
+* Returns - None.
+************************************************************************/
+void StatisticsResponse(struct bcm_mini_adapter *Adapter, void *pvBuffer)
+{
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__);
+ Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (unsigned int)Adapter->StatisticsPointer);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__);
+ return;
+}
+
+/**********************************************************************
+* Function - LinkControlResponseMessage()
+*
+* Description - This function handles the Link response packets.
+*
+* Parameters - Adapter : Pointer to the Adapter structure.
+* - pucBuffer: Starting address of Link response data.
+*
+* Returns - None.
+***********************************************************************/
+void LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
+{
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
+
+ if (*pucBuffer == LINK_UP_ACK) {
+ switch (*(pucBuffer+1)) {
+ case PHY_SYNC_ACHIVED: /* SYNCed UP */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED");
+
+ if (Adapter->LinkStatus == LINKUP_DONE)
+ beceem_protocol_reset(Adapter);
+
+ Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
+ Adapter->LinkStatus = PHY_SYNC_ACHIVED;
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = NO_NETWORK_ENTRY;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ LinkMessage(Adapter);
+ break;
+
+ case LINKUP_DONE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE");
+ Adapter->LinkStatus = LINKUP_DONE;
+ Adapter->bPHSEnabled = *(pucBuffer+3);
+ Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x\n", Adapter->bPHSEnabled);
+
+ if ((false == Adapter->bShutStatus) && (false == Adapter->IdleMode)) {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = NORMAL_OPERATION;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+ }
+ LinkMessage(Adapter);
+ break;
+
+ case WAIT_FOR_SYNC:
+ /*
+ * Driver to ignore the DREG_RECEIVED
+ * WiMAX Application should handle this Message
+ */
+ /* Adapter->liTimeSinceLastNetEntry = 0; */
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+ Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
+ Adapter->bTriedToWakeUpFromlowPowerMode = false;
+ Adapter->IdleMode = false;
+ beceem_protocol_reset(Adapter);
+
+ break;
+ case LINK_SHUTDOWN_REQ_FROM_FIRMWARE:
+ case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW:
+ {
+ HandleShutDownModeRequest(Adapter, pucBuffer);
+ }
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x", *(pucBuffer + 1));
+ break;
+ }
+ } else if (SET_MAC_ADDRESS_RESPONSE == *pucBuffer) {
+ PUCHAR puMacAddr = (pucBuffer + 1);
+ Adapter->LinkStatus = SYNC_UP_REQUEST;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP");
+ LinkMessage(Adapter);
+ memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE);
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====", __func__);
+ return;
+}
+
+void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
+{
+ int status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
+ struct timeval tv;
+ struct bcm_link_request stIdleResponse = {{0} };
+ memset(&tv, 0, sizeof(tv));
+ stIdleResponse.Leader.Status = IDLE_MESSAGE;
+ stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH;
+ stIdleResponse.szData[0] = GO_TO_IDLE_MODE_PAYLOAD;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, " ============>");
+
+ /*********************************
+ *down_trylock -
+ * if [ semaphore is available ]
+ * acquire semaphone and return value 0 ;
+ * else
+ * return non-zero value ;
+ *
+ ***********************************/
+
+ NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync);
+
+
+ if ((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) &&
+ (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) {
+
+ if (!NVMAccess)
+ up(&Adapter->NVMRdmWrmLock);
+
+ if (!lowPwrAbortMsg)
+ up(&Adapter->LowPowerModeSync);
+
+ stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!");
+ Adapter->bPreparingForLowPowerMode = false;
+ } else {
+ stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; /* 2; Idle ACK */
+ Adapter->StatisticsPointer = 0;
+
+ /* Wait for the LED to TURN OFF before sending ACK response */
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ int iRetVal = 0;
+
+ /* Wake the LED Thread with IDLEMODE_ENTER State */
+ Adapter->DriverState = LOWPOWER_MODE_ENTER;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld", jiffies);
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+
+ /* Wait for 1 SEC for LED to OFF */
+ iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
+
+ /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */
+ if (iRetVal <= 0) {
+ stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
+ Adapter->DriverState = NORMAL_OPERATION;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!");
+ }
+ }
+
+ if (stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "ACKING IDLE MODE !!!!!!!!!");
+ down(&Adapter->rdmwrmsync);
+ Adapter->bPreparingForLowPowerMode = TRUE;
+ up(&Adapter->rdmwrmsync);
+ /* Killing all URBS. */
+ if (Adapter->bDoSuspend == TRUE)
+ Bcm_kill_all_URBs((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
+ } else {
+ Adapter->bPreparingForLowPowerMode = false;
+ }
+
+ if (!NVMAccess)
+ up(&Adapter->NVMRdmWrmLock);
+
+ if (!lowPwrAbortMsg)
+ up(&Adapter->LowPowerModeSync);
+ }
+
+ status = CopyBufferToControlPacket(Adapter, &stIdleResponse);
+ if ((status != STATUS_SUCCESS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n");
+ Adapter->bPreparingForLowPowerMode = false;
+ StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
+ }
+ do_gettimeofday(&tv);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+/******************************************************************
+* Function - DumpPackInfo()
+*
+* Description - This function dumps the all Queue(PackInfo[]) details.
+*
+* Parameters - Adapter: Pointer to the Adapter structure.
+*
+* Returns - None.
+*******************************************************************/
+void DumpPackInfo(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiLoopIndex = 0;
+ unsigned int uiIndex = 0;
+ unsigned int uiClsfrIndex = 0;
+ struct bcm_classifier_rule *pstClassifierEntry = NULL;
+
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "*********** Showing Details Of Queue %d***** ******", uiLoopIndex);
+ if (false == Adapter->PackInfo[uiLoopIndex].bValid) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid is false for %X index\n", uiLoopIndex);
+ continue;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " Dumping SF Rule Entry For SFID %lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " ucDirection %X\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
+
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv6 Service Flow\n");
+ else
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv4 Service Flow\n");
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SF Traffic Priority %X\n", Adapter->PackInfo[uiLoopIndex].u8TrafficPriority);
+
+ for (uiClsfrIndex = 0; uiClsfrIndex < MAX_CLASSIFIERS; uiClsfrIndex++) {
+ pstClassifierEntry = &Adapter->astClassifierTable[uiClsfrIndex];
+ if (!pstClassifierEntry->bUsed)
+ continue;
+
+ if (pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID)
+ continue;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n", uiClsfrIndex, pstClassifierEntry->uiClassifierRuleIndex);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n", uiClsfrIndex, pstClassifierEntry->usVCID_Value);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n", uiClsfrIndex, pstClassifierEntry->bProtocolValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n", uiClsfrIndex, pstClassifierEntry->bTOSValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bDestIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bSrcIpValid);
+
+ for (uiIndex = 0; uiIndex < MAX_PORT_RANGE; uiIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeLo:%X\n", pstClassifierEntry->usSrcPortRangeLo[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeHi:%X\n", pstClassifierEntry->usSrcPortRangeHi[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeLo:%X\n", pstClassifierEntry->usDestPortRangeLo[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeHi:%X\n", pstClassifierEntry->usDestPortRangeHi[uiIndex]);
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPSourceAddressLength : 0x%x\n", pstClassifierEntry->ucIPSourceAddressLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPDestinationAddressLength : 0x%x\n", pstClassifierEntry->ucIPDestinationAddressLength);
+ for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPSourceAddressLength; uiIndex++) {
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpAddr :\n");
+ DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpMask :\n");
+ DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpAddr:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpMask:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]);
+ }
+ }
+
+ for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPDestinationAddressLength; uiIndex++) {
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpAddr :\n");
+ DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Addr);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpMask :\n");
+ DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Mask);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpAddr:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpMask:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]);
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucProtocol:0x%X\n", pstClassifierEntry->ucProtocol[0]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tu8ClassifierRulePriority:%X\n", pstClassifierEntry->u8ClassifierRulePriority);
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ulSFID:%lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "usVCID_Value:%X\n", Adapter->PackInfo[uiLoopIndex].usVCID_Value);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "PhsEnabled: 0x%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThreshold:%X\n", Adapter->PackInfo[uiLoopIndex].uiThreshold);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid:%X\n", Adapter->PackInfo[uiLoopIndex].bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bActive:%X\n", Adapter->PackInfo[uiLoopIndex].bActive);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "u8QueueType:%X\n", Adapter->PackInfo[uiLoopIndex].u8QueueType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxBucketSize:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPerSFTxResourceCount:%X\n", atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount));
+ /* DumpDebug(DUMP_INFO,("bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport)); */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentBytesOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentPacketsOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentPackets);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentDrainRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThisPeriodSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liDrainCalculated:%llX\n", Adapter->PackInfo[uiLoopIndex].liDrainCalculated);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentTokenCount:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liLastUpdateTokenAt:%llX\n", Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxAllowedRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPendedLast:%X\n", Adapter->PackInfo[uiLoopIndex].uiPendedLast);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "NumOfPacketsSent:%X\n", Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n", Adapter->PackInfo[uiLoopIndex].uiMaxLatency);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO,
+ DBG_LVL_ALL, "ServiceClassName: %*ph\n",
+ 4, Adapter->PackInfo[uiLoopIndex].
+ ucServiceClassName);
+/* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
+ * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes);
+ * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes);
+ * DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount));
+ */
+ }
+
+ for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aRxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aRxPktSizeHist[uiLoopIndex]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aTxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aTxPktSizeHist[uiLoopIndex]);
+
+ return;
+}
+
+int reset_card_proc(struct bcm_mini_adapter *ps_adapter)
+{
+ int retval = STATUS_SUCCESS;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_interface_adapter *psIntfAdapter = NULL;
+ unsigned int value = 0, uiResetValue = 0;
+ int bytes;
+
+ psIntfAdapter = ((struct bcm_interface_adapter *)(ps_adapter->pvInterfaceAdapter));
+ ps_adapter->bDDRInitDone = false;
+
+ if (ps_adapter->chip_id >= T3LPB) {
+ /* SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before */
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+
+ /* making bit[6...5] same as was before f/w download. this setting force the h/w to */
+ /* re-populated the SP RAM area with the string descriptor. */
+ value = value | (ps_adapter->syscfgBefFwDld & 0x00000060);
+ wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ }
+
+ /* killing all submitted URBs. */
+ psIntfAdapter->psAdapter->StopAllXaction = TRUE;
+ Bcm_kill_all_URBs(psIntfAdapter);
+ /* Reset the UMA-B Device */
+ if (ps_adapter->chip_id >= T3LPB) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Resetting UMA-B\n");
+ retval = usb_reset_device(psIntfAdapter->udev);
+ psIntfAdapter->psAdapter->StopAllXaction = false;
+
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval);
+ goto err_exit;
+ }
+
+ if (ps_adapter->chip_id == BCS220_2 ||
+ ps_adapter->chip_id == BCS220_2BC ||
+ ps_adapter->chip_id == BCS250_BC ||
+ ps_adapter->chip_id == BCS220_3) {
+
+ bytes = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
+ if (bytes < 0) {
+ retval = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
+ goto err_exit;
+ }
+ /* setting 0th bit */
+ value |= (1<<0);
+ retval = wrmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
+ goto err_exit;
+ }
+ }
+ } else {
+ bytes = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (bytes < 0) {
+ retval = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
+ goto err_exit;
+ }
+ value &= (~(1<<16));
+ retval = wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
+ goto err_exit;
+ }
+
+ /* Toggling the GPIO 8, 9 */
+ value = 0;
+ retval = wrmalt(ps_adapter, GPIO_OUTPUT_REGISTER, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
+ goto err_exit;
+ }
+ value = 0x300;
+ retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
+ goto err_exit;
+ }
+ mdelay(50);
+ }
+
+ /* ps_adapter->downloadDDR = false; */
+ if (ps_adapter->bFlashBoot) {
+ /* In flash boot mode MIPS state register has reverse polarity.
+ * So just or with setting bit 30.
+ * Make the MIPS in Reset state.
+ */
+ rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue));
+ uiResetValue |= (1<<30);
+ wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue));
+ }
+
+ if (ps_adapter->chip_id >= T3LPB) {
+ uiResetValue = 0;
+ /*
+ * WA for SYSConfig Issue.
+ * Read SYSCFG Twice to make it writable.
+ */
+ rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));
+ if (uiResetValue & (1<<4)) {
+ uiResetValue = 0;
+ rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); /* 2nd read to make it writable. */
+ uiResetValue &= (~(1<<4));
+ wrmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));
+ }
+ }
+ uiResetValue = 0;
+ wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue));
+
+err_exit:
+ psIntfAdapter->psAdapter->StopAllXaction = false;
+ return retval;
+}
+
+int run_card_proc(struct bcm_mini_adapter *ps_adapter)
+{
+ int status = STATUS_SUCCESS;
+ int bytes;
+
+ unsigned int value = 0;
+ {
+ bytes = rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value));
+ if (bytes < 0) {
+ status = bytes;
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
+ return status;
+ }
+
+ if (ps_adapter->bFlashBoot)
+ value &= (~(1<<30));
+ else
+ value |= (1<<30);
+
+ if (wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
+ return STATUS_FAILURE;
+ }
+ }
+ return status;
+}
+
+int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter)
+{
+ int status;
+ unsigned int value = 0;
+ /*
+ * Create the threads first and then download the
+ * Firm/DDR Settings..
+ */
+ status = create_worker_threads(ps_adapter);
+ if (status < 0)
+ return status;
+
+ status = bcm_parse_target_params(ps_adapter);
+ if (status)
+ return status;
+
+ if (ps_adapter->chip_id >= T3LPB) {
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ ps_adapter->syscfgBefFwDld = value;
+
+ if ((value & 0x60) == 0)
+ ps_adapter->bFlashBoot = TRUE;
+ }
+
+ reset_card_proc(ps_adapter);
+
+ /* Initializing the NVM. */
+ BcmInitNVM(ps_adapter);
+ status = ddr_init(ps_adapter);
+ if (status) {
+ pr_err(DRV_NAME "ddr_init Failed\n");
+ return status;
+ }
+
+ /* Download cfg file */
+ status = buffDnldVerify(ps_adapter,
+ (PUCHAR)ps_adapter->pstargetparams,
+ sizeof(struct bcm_target_params),
+ CONFIG_BEGIN_ADDR);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file");
+ goto OUT;
+ }
+
+ if (register_networkdev(ps_adapter)) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed.");
+ return -EIO;
+ }
+
+ if (false == ps_adapter->AutoFirmDld) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n");
+ /* If Auto f/w download is disable, register the control interface, */
+ /* register the control interface after the mailbox. */
+ if (register_control_device_interface(ps_adapter) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed.");
+ return -EIO;
+ }
+ return STATUS_SUCCESS;
+ }
+
+ /*
+ * Do the LED Settings here. It will be used by the Firmware Download
+ * Thread.
+ */
+
+ /*
+ * 1. If the LED Settings fails, do not stop and do the Firmware download.
+ * 2. This init would happened only if the cfg file is present, else
+ * call from the ioctl context.
+ */
+
+ status = InitLedSettings(ps_adapter);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "INIT LED FAILED\n");
+ return status;
+ }
+
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ ps_adapter->DriverState = DRIVER_INIT;
+ wake_up(&ps_adapter->LEDInfo.notify_led_event);
+ }
+
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ ps_adapter->DriverState = FW_DOWNLOAD;
+ wake_up(&ps_adapter->LEDInfo.notify_led_event);
+ }
+
+ value = 0;
+ wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
+ wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
+
+ if (ps_adapter->eNVMType == NVM_FLASH) {
+ status = PropagateCalParamsFromFlashToMemory(ps_adapter);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Propagation of Cal param failed ..");
+ goto OUT;
+ }
+ }
+
+ /* Download Firmare */
+ status = BcmFileDownload(ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR);
+ if (status != 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present...\n");
+ goto OUT;
+ }
+
+ status = run_card_proc(ps_adapter);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n");
+ goto OUT;
+ }
+
+ ps_adapter->fw_download_done = TRUE;
+ mdelay(10);
+
+OUT:
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ ps_adapter->DriverState = FW_DOWNLOAD_DONE;
+ wake_up(&ps_adapter->LEDInfo.notify_led_event);
+ }
+
+ return status;
+}
+
+static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter)
+{
+ struct file *flp = NULL;
+ char *buff;
+ int len = 0;
+
+ buff = kmalloc(BUFFER_1K, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ Adapter->pstargetparams = kmalloc(sizeof(struct bcm_target_params), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL) {
+ kfree(buff);
+ return -ENOMEM;
+ }
+
+ flp = open_firmware_file(Adapter, CFG_FILE);
+ if (!flp) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE\n", CFG_FILE);
+ kfree(buff);
+ kfree(Adapter->pstargetparams);
+ Adapter->pstargetparams = NULL;
+ return -ENOENT;
+ }
+ len = kernel_read(flp, 0, buff, BUFFER_1K);
+ filp_close(flp, NULL);
+
+ if (len != sizeof(struct bcm_target_params)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n");
+ kfree(buff);
+ kfree(Adapter->pstargetparams);
+ Adapter->pstargetparams = NULL;
+ return -ENOENT;
+ }
+
+ /* Check for autolink in config params */
+ /*
+ * Values in Adapter->pstargetparams are in network byte order
+ */
+ memcpy(Adapter->pstargetparams, buff, sizeof(struct bcm_target_params));
+ kfree(buff);
+ beceem_parse_target_struct(Adapter);
+ return STATUS_SUCCESS;
+}
+
+void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
+
+ if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) {
+ pr_info(DRV_NAME ": AutoSyncup is Disabled\n");
+ Adapter->AutoSyncup = false;
+ } else {
+ pr_info(DRV_NAME ": AutoSyncup is Enabled\n");
+ Adapter->AutoSyncup = TRUE;
+ }
+
+ if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) {
+ pr_info(DRV_NAME ": Enabling autolink up");
+ Adapter->AutoLinkUp = TRUE;
+ } else {
+ pr_info(DRV_NAME ": Disabling autolink up");
+ Adapter->AutoLinkUp = false;
+ }
+ /* Setting the DDR Setting.. */
+ Adapter->DDRSetting = (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >> 8)&0x0F;
+ Adapter->ulPowerSaveMode = (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F;
+ pr_info(DRV_NAME ": DDR Setting: %x\n", Adapter->DDRSetting);
+ pr_info(DRV_NAME ": Power Save Mode: %lx\n", Adapter->ulPowerSaveMode);
+ if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) {
+ pr_info(DRV_NAME ": Enabling Auto Firmware Download\n");
+ Adapter->AutoFirmDld = TRUE;
+ } else {
+ pr_info(DRV_NAME ": Disabling Auto Firmware Download\n");
+ Adapter->AutoFirmDld = false;
+ }
+ uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6);
+ Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01;
+ pr_info(DRV_NAME ": MIPSConfig : 0x%X\n", Adapter->bMipsConfig);
+ /* used for backward compatibility. */
+ Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01;
+ Adapter->PmuMode = (uiHostDrvrCfg6 >> 24) & 0x03;
+ pr_info(DRV_NAME ": PMU MODE: %x", Adapter->PmuMode);
+
+ if ((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT) & (0x01)) {
+ Adapter->bDoSuspend = TRUE;
+ pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile");
+ }
+
+ uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag);
+ pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n", uiEEPROMFlag);
+ Adapter->eNVMType = (enum bcm_nvm_type)((uiEEPROMFlag>>4)&0x3);
+ Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1;
+ Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4));
+ Adapter->bSectorSizeOverride = (bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1;
+
+ if (ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x01)
+ Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE;
+
+ if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
+ doPowerAutoCorrection(Adapter);
+}
+
+static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
+{
+ unsigned int reporting_mode;
+
+ reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02;
+ psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1);
+
+ if (reporting_mode == TRUE) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "can't do suspen/resume as reporting mode is enable");
+ psAdapter->bDoSuspend = false;
+ }
+
+ if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) {
+ /* If reporting mode is enable, switch PMU to PMC */
+ {
+ psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING;
+ psAdapter->bDoSuspend = false;
+ }
+
+ /* clearing space bit[15..12] */
+ psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12)));
+ /* placing the power save mode option */
+ psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12));
+ } else if (psAdapter->bIsAutoCorrectEnabled == false) {
+ /* remove the autocorrect disable bit set before dumping. */
+ psAdapter->ulPowerSaveMode &= ~(1 << 3);
+ psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15));
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode);
+ }
+}
+
+static void convertEndian(unsigned char rwFlag, unsigned int *puiBuffer, unsigned int uiByteCount)
+{
+ unsigned int uiIndex = 0;
+
+ if (RWM_WRITE == rwFlag) {
+ for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++)
+ puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]);
+ } else {
+ for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++)
+ puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]);
+ }
+}
+
+int rdm(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
+{
+ return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
+ uiAddress, pucBuff, sSize);
+}
+
+int wrm(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
+{
+ int iRetVal;
+
+ iRetVal = Adapter->interface_wrm(Adapter->pvInterfaceAdapter,
+ uiAddress, pucBuff, sSize);
+ return iRetVal;
+}
+
+int wrmalt(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
+{
+ convertEndian(RWM_WRITE, pucBuff, size);
+ return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
+}
+
+int rdmalt(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
+{
+ int uiRetVal = 0;
+
+ uiRetVal = rdm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
+ convertEndian(RWM_READ, (unsigned int *)pucBuff, size);
+
+ return uiRetVal;
+}
+
+int wrmWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
+{
+ int status = STATUS_SUCCESS;
+ down(&Adapter->rdmwrmsync);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ status = -EACCES;
+ goto exit;
+ }
+
+ status = wrm(Adapter, uiAddress, pucBuff, sSize);
+exit:
+ up(&Adapter->rdmwrmsync);
+ return status;
+}
+
+int wrmaltWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
+{
+ int iRetVal = STATUS_SUCCESS;
+
+ down(&Adapter->rdmwrmsync);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ iRetVal = -EACCES;
+ goto exit;
+ }
+
+ iRetVal = wrmalt(Adapter, uiAddress, pucBuff, size);
+exit:
+ up(&Adapter->rdmwrmsync);
+ return iRetVal;
+}
+
+int rdmaltWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
+{
+ int uiRetVal = STATUS_SUCCESS;
+
+ down(&Adapter->rdmwrmsync);
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ uiRetVal = -EACCES;
+ goto exit;
+ }
+
+ uiRetVal = rdmalt(Adapter, uiAddress, pucBuff, size);
+exit:
+ up(&Adapter->rdmwrmsync);
+ return uiRetVal;
+}
+
+static void HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
+{
+ int clear_abort_pattern = 0, Status = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
+ /* target has woken up From Shut Down */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
+ Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (unsigned int *)&clear_abort_pattern, sizeof(clear_abort_pattern));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
+ return;
+ }
+
+ if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
+ msleep(100);
+ InterfaceHandleShutdownModeWakeup(Adapter);
+ msleep(100);
+ }
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = NO_NETWORK_ENTRY;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ Adapter->bTriedToWakeUpFromlowPowerMode = false;
+ Adapter->bShutStatus = false;
+ wake_up(&Adapter->lowpower_mode_wait_queue);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
+}
+
+static void SendShutModeResponse(struct bcm_mini_adapter *Adapter)
+{
+ struct bcm_link_request stShutdownResponse;
+ unsigned int NVMAccess = 0, lowPwrAbortMsg = 0;
+ unsigned int Status = 0;
+
+ memset(&stShutdownResponse, 0, sizeof(struct bcm_link_request));
+ stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ;
+ stShutdownResponse.Leader.PLength = 8; /* 8 bytes; */
+ stShutdownResponse.szData[0] = LINK_UP_ACK;
+ stShutdownResponse.szData[1] = LINK_SHUTDOWN_REQ_FROM_FIRMWARE;
+
+ /*********************************
+ * down_trylock -
+ * if [ semaphore is available ]
+ * acquire semaphone and return value 0 ;
+ * else
+ * return non-zero value ;
+ *
+ ***********************************/
+
+ NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync);
+
+ if (NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) {
+ if (!NVMAccess)
+ up(&Adapter->NVMRdmWrmLock);
+
+ if (!lowPwrAbortMsg)
+ up(&Adapter->LowPowerModeSync);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n");
+ stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
+ Adapter->bPreparingForLowPowerMode = false;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n");
+ stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER; /* ShutDown ACK */
+
+ /* Wait for the LED to TURN OFF before sending ACK response */
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ int iRetVal = 0;
+
+ /* Wake the LED Thread with LOWPOWER_MODE_ENTER State */
+ Adapter->DriverState = LOWPOWER_MODE_ENTER;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+
+ /* Wait for 1 SEC for LED to OFF */
+ iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
+
+ /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */
+ if (iRetVal <= 0) {
+ stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
+ Adapter->DriverState = NO_NETWORK_ENTRY;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+ }
+
+ if (stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ACKING SHUTDOWN MODE !!!!!!!!!");
+ down(&Adapter->rdmwrmsync);
+ Adapter->bPreparingForLowPowerMode = TRUE;
+ up(&Adapter->rdmwrmsync);
+ /* Killing all URBS. */
+ if (Adapter->bDoSuspend == TRUE)
+ Bcm_kill_all_URBs((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
+ } else {
+ Adapter->bPreparingForLowPowerMode = false;
+ }
+
+ if (!NVMAccess)
+ up(&Adapter->NVMRdmWrmLock);
+
+ if (!lowPwrAbortMsg)
+ up(&Adapter->LowPowerModeSync);
+ }
+
+ Status = CopyBufferToControlPacket(Adapter, &stShutdownResponse);
+ if ((Status != STATUS_SUCCESS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "fail to send the Idle mode Request\n");
+ Adapter->bPreparingForLowPowerMode = false;
+ StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
+ }
+}
+
+static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
+{
+ unsigned int uiResetValue = 0;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
+
+ if (*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW) {
+ HandleShutDownModeWakeup(Adapter);
+ } else if (*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) {
+ /* Target wants to go to Shut Down Mode */
+ /* InterfacePrepareForShutdown(Adapter); */
+ if (Adapter->chip_id == BCS220_2 ||
+ Adapter->chip_id == BCS220_2BC ||
+ Adapter->chip_id == BCS250_BC ||
+ Adapter->chip_id == BCS220_3) {
+
+ rdmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4);
+ uiResetValue |= (1<<17);
+ wrmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4);
+ }
+
+ SendShutModeResponse(Adapter);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
+ return;
+}
+
+void ResetCounters(struct bcm_mini_adapter *Adapter)
+{
+ beceem_protocol_reset(Adapter);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ atomic_set(&Adapter->TotalPacketCount, 0);
+ Adapter->fw_download_done = false;
+ Adapter->LinkStatus = 0;
+ Adapter->AutoLinkUp = false;
+ Adapter->IdleMode = false;
+ Adapter->bShutStatus = false;
+}
+
+struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP)
+{
+ unsigned int uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIP) &&
+ !Adapter->astFragmentedPktClassifierTable[uiIndex].bOutOfOrderFragment)
+
+ return Adapter->astFragmentedPktClassifierTable[uiIndex].pstMatchedClassifierEntry;
+ }
+ return NULL;
+}
+
+void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo)
+{
+ unsigned int uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) {
+ memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(struct bcm_fragmented_packet_info));
+ break;
+ }
+ }
+}
+
+void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIp)
+{
+ unsigned int uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIp))
+
+ memset(&Adapter->astFragmentedPktClassifierTable[uiIndex], 0, sizeof(struct bcm_fragmented_packet_info));
+ }
+}
+
+void update_per_cid_rx(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int qindex = 0;
+
+ if ((jiffies - Adapter->liDrainCalculated) < XSECONDS)
+ return;
+
+ for (qindex = 0; qindex < HiPriority; qindex++) {
+ if (Adapter->PackInfo[qindex].ucDirection == 0) {
+ Adapter->PackInfo[qindex].uiCurrentRxRate =
+ (Adapter->PackInfo[qindex].uiCurrentRxRate +
+ Adapter->PackInfo[qindex].uiThisPeriodRxBytes) / 2;
+
+ Adapter->PackInfo[qindex].uiThisPeriodRxBytes = 0;
+ } else {
+ Adapter->PackInfo[qindex].uiCurrentDrainRate =
+ (Adapter->PackInfo[qindex].uiCurrentDrainRate +
+ Adapter->PackInfo[qindex].uiThisPeriodSentBytes) / 2;
+ Adapter->PackInfo[qindex].uiThisPeriodSentBytes = 0;
+ }
+ }
+ Adapter->liDrainCalculated = jiffies;
+}
+
+void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter)
+{
+ int iIndex = 0;
+ u32 uibuff[MAX_TARGET_DSX_BUFFERS];
+ int bytes;
+
+ if (!atomic_read(&Adapter->uiMBupdate))
+ return;
+
+ bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (unsigned int *)uibuff, sizeof(unsigned int) * MAX_TARGET_DSX_BUFFERS);
+ if (bytes < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
+ return;
+ }
+
+ for (iIndex = 0; iIndex < HiPriority; iIndex++) {
+ if (Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection) {
+ if (Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS)
+ atomic_set(&Adapter->PackInfo[iIndex].uiPerSFTxResourceCount, uibuff[Adapter->PackInfo[iIndex].usVCID_Value]);
+ else
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x\n", Adapter->PackInfo[iIndex].usVCID_Value);
+ }
+ }
+ atomic_set(&Adapter->uiMBupdate, false);
+}
+
+void flush_queue(struct bcm_mini_adapter *Adapter, unsigned int iQIndex)
+{
+ struct sk_buff *PacketToDrop = NULL;
+ struct net_device_stats *netstats = &Adapter->dev->stats;
+ spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
+
+ while (Adapter->PackInfo[iQIndex].FirstTxQueue && atomic_read(&Adapter->TotalPacketCount)) {
+ PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
+ if (PacketToDrop && PacketToDrop->len) {
+ netstats->tx_dropped++;
+ DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, Adapter->PackInfo[iQIndex].LastTxQueue);
+ Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
+ Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= PacketToDrop->len;
+
+ /* Adding dropped statistics */
+ Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len;
+ Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
+ dev_kfree_skb(PacketToDrop);
+ atomic_dec(&Adapter->TotalPacketCount);
+ }
+ }
+ spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
+}
+
+static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter)
+{
+ int i;
+ if (netif_msg_link(Adapter))
+ pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name);
+
+ netif_carrier_off(Adapter->dev);
+ netif_stop_queue(Adapter->dev);
+
+ Adapter->IdleMode = false;
+ Adapter->LinkUpStatus = false;
+ ClearTargetDSXBuffer(Adapter, 0, TRUE);
+ /* Delete All Classifier Rules */
+
+ for (i = 0; i < HiPriority; i++)
+ DeleteAllClassifiersForSF(Adapter, i);
+
+ flush_all_queues(Adapter);
+
+ if (Adapter->TimerActive == TRUE)
+ Adapter->TimerActive = false;
+
+ memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(struct bcm_fragmented_packet_info) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES);
+
+ for (i = 0; i < HiPriority; i++) {
+ /* resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. */
+ /* It is same between MIBs and SF. */
+ memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, 0, sizeof(struct bcm_mibs_parameters));
+ }
+}
diff --git a/drivers/staging/bcm/PHSDefines.h b/drivers/staging/bcm/PHSDefines.h
new file mode 100644
index 00000000000..cd78ee4ffa2
--- /dev/null
+++ b/drivers/staging/bcm/PHSDefines.h
@@ -0,0 +1,94 @@
+#ifndef BCM_PHS_DEFINES_H
+#define BCM_PHS_DEFINES_H
+
+#define PHS_INVALID_TABLE_INDEX 0xffffffff
+#define PHS_MEM_TAG "_SHP"
+
+/* PHS Defines */
+#define STATUS_PHS_COMPRESSED 0xa1
+#define STATUS_PHS_NOCOMPRESSION 0xa2
+#define APPLY_PHS 1
+#define MAX_NO_BIT 7
+#define ZERO_PHSI 0
+#define VERIFY 0
+#define SIZE_MULTIPLE_32 4
+#define UNCOMPRESSED_PACKET 0
+#define DYNAMIC 0
+#define SUPPRESS 0x80
+#define NO_CLASSIFIER_MATCH 0
+#define SEND_PACKET_UNCOMPRESSED 0
+#define PHSI_IS_ZERO 0
+#define PHSI_LEN 1
+#define ERROR_LEN 0
+#define PHS_BUFFER_SIZE 1532
+#define MAX_PHSRULE_PER_SF 20
+#define MAX_SERVICEFLOWS 17
+
+/* PHS Error Defines */
+#define PHS_SUCCESS 0
+#define ERR_PHS_INVALID_DEVICE_EXETENSION 0x800
+#define ERR_PHS_INVALID_PHS_RULE 0x801
+#define ERR_PHS_RULE_ALREADY_EXISTS 0x802
+#define ERR_SF_MATCH_FAIL 0x803
+#define ERR_INVALID_CLASSIFIERTABLE_FOR_SF 0x804
+#define ERR_SFTABLE_FULL 0x805
+#define ERR_CLSASSIFIER_TABLE_FULL 0x806
+#define ERR_PHSRULE_MEMALLOC_FAIL 0x807
+#define ERR_CLSID_MATCH_FAIL 0x808
+#define ERR_PHSRULE_MATCH_FAIL 0x809
+
+struct bcm_phs_rule {
+ u8 u8PHSI;
+ u8 u8PHSFLength;
+ u8 u8PHSF[MAX_PHS_LENGTHS];
+ u8 u8PHSMLength;
+ u8 u8PHSM[MAX_PHS_LENGTHS];
+ u8 u8PHSS;
+ u8 u8PHSV;
+ u8 u8RefCnt;
+ u8 bUnclassifiedPHSRule;
+ u8 u8Reserved[3];
+ long PHSModifiedBytes;
+ unsigned long PHSModifiedNumPackets;
+ unsigned long PHSErrorNumPackets;
+};
+
+enum bcm_phs_classifier_context {
+ eActiveClassifierRuleContext,
+ eOldClassifierRuleContext
+};
+
+struct bcm_phs_classifier_entry {
+ u8 bUsed;
+ u16 uiClassifierRuleId;
+ u8 u8PHSI;
+ struct bcm_phs_rule *pstPhsRule;
+ u8 bUnclassifiedPHSRule;
+};
+
+struct bcm_phs_classifier_table {
+ u16 uiTotalClassifiers;
+ struct bcm_phs_classifier_entry stActivePhsRulesList[MAX_PHSRULE_PER_SF];
+ struct bcm_phs_classifier_entry stOldPhsRulesList[MAX_PHSRULE_PER_SF];
+ u16 uiOldestPhsRuleIndex;
+};
+
+struct bcm_phs_entry {
+ u8 bUsed;
+ u16 uiVcid;
+ struct bcm_phs_classifier_table *pstClassifierTable;
+};
+
+struct bcm_phs_table {
+ u16 uiTotalServiceFlows;
+ struct bcm_phs_entry stSFList[MAX_SERVICEFLOWS];
+};
+
+struct bcm_phs_extension {
+ /* PHS Specific data */
+ struct bcm_phs_table *pstServiceFlowPhsRulesTable;
+ void *CompressedTxBuffer;
+ void *UnCompressedRxBuffer;
+};
+
+#endif
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
new file mode 100644
index 00000000000..07c5a0bae1e
--- /dev/null
+++ b/drivers/staging/bcm/PHSModule.c
@@ -0,0 +1,1448 @@
+#include "headers.h"
+
+static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+
+static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+
+static UINT CreateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, enum bcm_phs_classifier_context eClsContext, B_UINT8 u8AssociatedPHSI);
+
+static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
+
+static bool ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
+
+static bool DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
+
+static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
+
+static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
+
+static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
+
+static int phs_compress(struct bcm_phs_rule *phs_members, unsigned char *in_buf,
+ unsigned char *out_buf, unsigned int *header_size, UINT *new_header_size);
+
+static int verify_suppress_phsf(unsigned char *in_buffer, unsigned char *out_buffer,
+ unsigned char *phsf, unsigned char *phsm, unsigned int phss, unsigned int phsv, UINT *new_header_size);
+
+static int phs_decompress(unsigned char *in_buf, unsigned char *out_buf,
+ struct bcm_phs_rule *phs_rules, UINT *header_size);
+
+static ULONG PhsCompress(void *pvContext,
+ B_UINT16 uiVcid,
+ B_UINT16 uiClsId,
+ void *pvInputBuffer,
+ void *pvOutputBuffer,
+ UINT *pOldHeaderSize,
+ UINT *pNewHeaderSize);
+
+static ULONG PhsDeCompress(void *pvContext,
+ B_UINT16 uiVcid,
+ void *pvInputBuffer,
+ void *pvOutputBuffer,
+ UINT *pInHeaderSize,
+ UINT *pOutHeaderSize);
+
+#define IN
+#define OUT
+
+/*
+ * Function: PHSTransmit
+ * Description: This routine handle PHS(Payload Header Suppression for Tx path.
+ * It extracts a fragment of the NDIS_PACKET containing the header
+ * to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
+ * The header data after suppression is copied back to the NDIS_PACKET.
+ *
+ * Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
+ * IN Packet - NDIS packet containing data to be transmitted
+ * IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
+ * identify PHS rule to be applied.
+ * B_UINT16 uiClassifierRuleID - Classifier Rule ID
+ * BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
+ *
+ * Return: STATUS_SUCCESS - If the send was successful.
+ * Other - If an error occurred.
+ */
+
+int PHSTransmit(struct bcm_mini_adapter *Adapter,
+ struct sk_buff **pPacket,
+ USHORT Vcid,
+ B_UINT16 uiClassifierRuleID,
+ bool bHeaderSuppressionEnabled,
+ UINT *PacketLen,
+ UCHAR bEthCSSupport)
+{
+ /* PHS Sepcific */
+ UINT unPHSPktHdrBytesCopied = 0;
+ UINT unPhsOldHdrSize = 0;
+ UINT unPHSNewPktHeaderLen = 0;
+ /* Pointer to PHS IN Hdr Buffer */
+ PUCHAR pucPHSPktHdrInBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
+ /* Pointer to PHS OUT Hdr Buffer */
+ PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
+ UINT usPacketType;
+ UINT BytesToRemove = 0;
+ bool bPHSI = 0;
+ LONG ulPhsStatus = 0;
+ UINT numBytesCompressed = 0;
+ struct sk_buff *newPacket = NULL;
+ struct sk_buff *Packet = *pPacket;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
+
+ if (!bEthCSSupport)
+ BytesToRemove = ETH_HLEN;
+ /*
+ * Accumulate the header upto the size we support suppression
+ * from NDIS packet
+ */
+
+ usPacketType = ((struct ethhdr *)(Packet->data))->h_proto;
+
+ pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
+ /* considering data after ethernet header */
+ if ((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
+ unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
+ else
+ unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
+
+ if ((unPHSPktHdrBytesCopied > 0) &&
+ (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
+
+ /*
+ * Step 2 Suppress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
+ * Suppress only if IP Header and PHS Enabled For the Service Flow
+ */
+ if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
+ (usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
+ (bHeaderSuppressionEnabled)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nTrying to PHS Compress Using Classifier rule 0x%X", uiClassifierRuleID);
+ unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
+ ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
+ Vcid,
+ uiClassifierRuleID,
+ pucPHSPktHdrInBuf,
+ pucPHSPktHdrOutBuf,
+ &unPhsOldHdrSize,
+ &unPHSNewPktHeaderLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nPHS Old header Size : %d New Header Size %d\n", unPhsOldHdrSize, unPHSNewPktHeaderLen);
+
+ if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
+
+ if (ulPhsStatus == STATUS_PHS_COMPRESSED)
+ bPHSI = *pucPHSPktHdrOutBuf;
+
+ ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
+ }
+
+ if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "PHS Sending packet Compressed");
+
+ if (skb_cloned(Packet)) {
+ newPacket = skb_copy(Packet, GFP_ATOMIC);
+
+ if (newPacket == NULL)
+ return STATUS_FAILURE;
+
+ dev_kfree_skb(Packet);
+ *pPacket = Packet = newPacket;
+ pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
+ }
+
+ numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen + PHSI_LEN);
+
+ memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
+ memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
+ skb_pull(Packet, numBytesCompressed);
+
+ return STATUS_SUCCESS;
+ } else {
+ /* if one byte headroom is not available, increase it through skb_cow */
+ if (!(skb_headroom(Packet) > 0)) {
+
+ if (skb_cow(Packet, 1)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
+ return STATUS_FAILURE;
+ }
+ }
+ skb_push(Packet, 1);
+
+ /*
+ * CAUTION: The MAC Header is getting corrupted
+ * here for IP CS - can be saved by copying 14
+ * Bytes. not needed .... hence corrupting it.
+ */
+ *(Packet->data + BytesToRemove) = bPHSI;
+ return STATUS_SUCCESS;
+ }
+ } else {
+
+ if (!bHeaderSuppressionEnabled)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nHeader Suppression Disabled For SF: No PHS\n");
+
+ return STATUS_SUCCESS;
+ }
+ }
+
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS"); */
+ return STATUS_SUCCESS;
+}
+
+int PHSReceive(struct bcm_mini_adapter *Adapter,
+ USHORT usVcid,
+ struct sk_buff *packet,
+ UINT *punPacketLen,
+ UCHAR *pucEthernetHdr,
+ UINT bHeaderSuppressionEnabled)
+{
+ u32 nStandardPktHdrLen = 0;
+ u32 nTotalsuppressedPktHdrBytes = 0;
+ int ulPhsStatus = 0;
+ PUCHAR pucInBuff = NULL;
+ UINT TotalBytesAdded = 0;
+
+ if (!bHeaderSuppressionEnabled) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nPhs Disabled for incoming packet");
+ return ulPhsStatus;
+ }
+
+ pucInBuff = packet->data;
+
+ /* Restore PHS suppressed header */
+ nStandardPktHdrLen = packet->len;
+ ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
+ usVcid,
+ pucInBuff,
+ Adapter->ucaPHSPktRestoreBuf,
+ &nTotalsuppressedPktHdrBytes,
+ &nStandardPktHdrLen);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+ nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
+
+ if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
+ skb_pull(packet, 1);
+ return STATUS_SUCCESS;
+ } else {
+ TotalBytesAdded = nStandardPktHdrLen - nTotalsuppressedPktHdrBytes - PHSI_LEN;
+
+ if (TotalBytesAdded) {
+ if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
+ skb_push(packet, TotalBytesAdded);
+ else {
+ if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
+ return STATUS_FAILURE;
+ }
+
+ skb_push(packet, TotalBytesAdded);
+ }
+ }
+
+ memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void DumpFullPacket(UCHAR *pBuf, UINT nPktLen)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dumping Data Packet");
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, pBuf, nPktLen);
+}
+
+/*
+ * Procedure: phs_init
+ *
+ * Description: This routine is responsible for allocating memory for classifier and
+ * PHS rules.
+ *
+ * Arguments:
+ * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
+ *
+ * Returns:
+ * TRUE(1) -If allocation of memory was successful.
+ * FALSE -If allocation of memory fails.
+ */
+int phs_init(struct bcm_phs_extension *pPhsdeviceExtension, struct bcm_mini_adapter *Adapter)
+{
+ int i;
+ struct bcm_phs_table *pstServiceFlowTable;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function");
+
+ if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
+ return -EINVAL;
+
+ pPhsdeviceExtension->pstServiceFlowPhsRulesTable = kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
+
+ if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
+ return -ENOMEM;
+ }
+
+ pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+ struct bcm_phs_entry sServiceFlow = pstServiceFlowTable->stSFList[i];
+ sServiceFlow.pstClassifierTable = kzalloc(sizeof(struct bcm_phs_classifier_table), GFP_KERNEL);
+ if (!sServiceFlow.pstClassifierTable) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
+ pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
+ return -ENOMEM;
+ }
+ }
+
+ pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
+ if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
+ pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
+ return -ENOMEM;
+ }
+
+ pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
+ if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ kfree(pPhsdeviceExtension->CompressedTxBuffer);
+ free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
+ pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
+ return -ENOMEM;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
+ return STATUS_SUCCESS;
+}
+
+int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
+{
+ if (pPHSDeviceExt->pstServiceFlowPhsRulesTable) {
+ free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
+ pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
+ }
+
+ kfree(pPHSDeviceExt->CompressedTxBuffer);
+ pPHSDeviceExt->CompressedTxBuffer = NULL;
+
+ kfree(pPHSDeviceExt->UnCompressedRxBuffer);
+ pPHSDeviceExt->UnCompressedRxBuffer = NULL;
+
+ return 0;
+}
+
+/*
+ * PHS functions
+ * PhsUpdateClassifierRule
+ *
+ * Routine Description:
+ * Exported function to add or modify a PHS Rule.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
+ * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
+ * IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsUpdateClassifierRule(IN void *pvContext,
+ IN B_UINT16 uiVcid ,
+ IN B_UINT16 uiClsId ,
+ IN struct bcm_phs_rule *psPhsRule,
+ IN B_UINT8 u8AssociatedPHSI)
+{
+ ULONG lStatus = 0;
+ UINT nSFIndex = 0;
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS With Corr2 Changes\n");
+
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Invalid Device Extension\n");
+ return ERR_PHS_INVALID_DEVICE_EXETENSION;
+ }
+
+ if (u8AssociatedPHSI == 0)
+ return ERR_PHS_INVALID_PHS_RULE;
+
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+ uiVcid, &pstServiceFlowEntry);
+
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ /* This is a new SF. Create a mapping entry for this */
+ lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
+ pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
+ return lStatus;
+ }
+
+ /* SF already Exists Add PHS Rule to existing SF */
+ lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
+ pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
+
+ return lStatus;
+}
+
+/*
+ * PhsDeletePHSRule
+ *
+ * Routine Description:
+ * Deletes the specified phs Rule within Vcid
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
+ * IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeletePHSRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT8 u8PHSI)
+{
+ UINT nSFIndex = 0, nClsidIndex = 0;
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
+
+ if (pDeviceExtension) {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
+
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+ return ERR_SF_MATCH_FAIL;
+ }
+
+ pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+ if (pstClassifierRulesTable) {
+ for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) {
+
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
+
+ memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
+ sizeof(struct bcm_phs_classifier_entry));
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * PhsDeleteClassifierRule
+ *
+ * Routine Description:
+ * Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
+ * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeleteClassifierRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT16 uiClsId)
+{
+ UINT nSFIndex = 0, nClsidIndex = 0;
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ if (pDeviceExtension) {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+ return ERR_SF_MATCH_FAIL;
+ }
+
+ nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
+ uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
+
+ if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
+ if (pstClassifierEntry->pstPhsRule) {
+ if (pstClassifierEntry->pstPhsRule->u8RefCnt)
+ pstClassifierEntry->pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
+ kfree(pstClassifierEntry->pstPhsRule);
+ }
+ memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
+ }
+
+ nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
+ uiClsId, eOldClassifierRuleContext, &pstClassifierEntry);
+
+ if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) {
+ kfree(pstClassifierEntry->pstPhsRule);
+ memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry));
+ }
+ }
+ return 0;
+}
+
+/*
+ * PhsDeleteSFRules
+ *
+ * Routine Description:
+ * Exported function to Delete a all PHS Rules for the SFID.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context
+ * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
+{
+ UINT nSFIndex = 0, nClsidIndex = 0;
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "====>\n");
+
+ if (pDeviceExtension) {
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+ uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
+ return ERR_SF_MATCH_FAIL;
+ }
+
+ pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
+ if (pstClassifierRulesTable) {
+ for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
+
+ pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule = NULL;
+ }
+ memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
+ if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
+ kfree(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule);
+
+ pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule = NULL;
+ }
+ memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
+ }
+ }
+ pstServiceFlowEntry->bUsed = false;
+ pstServiceFlowEntry->uiVcid = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * PhsCompress
+ *
+ * Routine Description:
+ * Exported function to compress the data using PHS.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context.
+ * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies.
+ * IN UINT uiClsId - The Classifier ID to which current packet header compression applies.
+ * IN void *pvInputBuffer - The Input buffer containg packet header data
+ * IN void *pvOutputBuffer - The output buffer returned by this function after PHS
+ * IN UINT *pOldHeaderSize - The actual size of the header before PHS
+ * IN UINT *pNewHeaderSize - The new size of the header after applying PHS
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+static ULONG PhsCompress(IN void *pvContext,
+ IN B_UINT16 uiVcid,
+ IN B_UINT16 uiClsId,
+ IN void *pvInputBuffer,
+ OUT void *pvOutputBuffer,
+ OUT UINT *pOldHeaderSize,
+ OUT UINT *pNewHeaderSize)
+{
+ UINT nSFIndex = 0, nClsidIndex = 0;
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
+ struct bcm_phs_rule *pstPhsRule = NULL;
+ ULONG lStatus = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Invalid Device Extension\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
+ return lStatus;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Suppressing header\n");
+
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+ uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "SFID Match Failed\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
+ return lStatus;
+ }
+
+ nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
+ uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
+
+ if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "No PHS Rule Defined For Classifier\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
+ return lStatus;
+ }
+
+ /* get rule from SF id,Cls ID pair and proceed */
+ pstPhsRule = pstClassifierEntry->pstPhsRule;
+ if (!ValidatePHSRuleComplete(pstPhsRule)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS Rule Defined For Classifier But Not Complete\n");
+ lStatus = STATUS_PHS_NOCOMPRESSION;
+ return lStatus;
+ }
+
+ /* Compress Packet */
+ lStatus = phs_compress(pstPhsRule, (PUCHAR)pvInputBuffer,
+ (PUCHAR)pvOutputBuffer, pOldHeaderSize, pNewHeaderSize);
+
+ if (lStatus == STATUS_PHS_COMPRESSED) {
+ pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
+ pstPhsRule->PHSModifiedNumPackets++;
+ } else
+ pstPhsRule->PHSErrorNumPackets++;
+
+ return lStatus;
+}
+
+/*
+ * PhsDeCompress
+ *
+ * Routine Description:
+ * Exported function to restore the packet header in Rx path.
+ *
+ * Arguments:
+ * IN void* pvContext - PHS Driver Specific Context.
+ * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies.
+ * IN void *pvInputBuffer - The Input buffer containg suppressed packet header data
+ * OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
+ * OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter.
+ *
+ * Return Value:
+ *
+ * 0 if successful,
+ * >0 Error.
+ */
+static ULONG PhsDeCompress(IN void *pvContext,
+ IN B_UINT16 uiVcid,
+ IN void *pvInputBuffer,
+ OUT void *pvOutputBuffer,
+ OUT UINT *pInHeaderSize,
+ OUT UINT *pOutHeaderSize)
+{
+ UINT nSFIndex = 0, nPhsRuleIndex = 0;
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_phs_rule *pstPhsRule = NULL;
+ UINT phsi;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
+
+ *pInHeaderSize = 0;
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Invalid Device Extension\n");
+ return ERR_PHS_INVALID_DEVICE_EXETENSION;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Restoring header\n");
+
+ phsi = *((unsigned char *)(pvInputBuffer));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "PHSI To Be Used For restore : %x\n", phsi);
+ if (phsi == UNCOMPRESSED_PACKET)
+ return STATUS_PHS_NOCOMPRESSION;
+
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
+ uiVcid, &pstServiceFlowEntry);
+ if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "SFID Match Failed During Lookup\n");
+ return ERR_SF_MATCH_FAIL;
+ }
+
+ nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, phsi,
+ eActiveClassifierRuleContext, &pstPhsRule);
+ if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
+ /* Phs Rule does not exist in active rules table. Lets try in the old rules table. */
+ nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
+ phsi, eOldClassifierRuleContext, &pstPhsRule);
+ if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
+ return ERR_PHSRULE_MATCH_FAIL;
+ }
+
+ *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
+ (PUCHAR)pvOutputBuffer, pstPhsRule, pOutHeaderSize);
+
+ pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
+
+ pstPhsRule->PHSModifiedNumPackets++;
+ return STATUS_PHS_COMPRESSED;
+}
+
+/*
+ * Procedure: free_phs_serviceflow_rules
+ *
+ * Description: This routine is responsible for freeing memory allocated for PHS rules.
+ *
+ * Arguments:
+ * rules - ptr to S_SERVICEFLOW_TABLE structure.
+ *
+ * Returns:
+ * Does not return any value.
+ */
+static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable)
+{
+ int i, j;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
+
+ if (psServiceFlowRulesTable) {
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+ struct bcm_phs_entry stServiceFlowEntry = psServiceFlowRulesTable->stSFList[i];
+ struct bcm_phs_classifier_table *pstClassifierRulesTable = stServiceFlowEntry.pstClassifierTable;
+
+ if (pstClassifierRulesTable) {
+ for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+ if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt)
+ kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
+
+ pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
+ }
+
+ if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) {
+
+ if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
+ pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt--;
+
+ if (0 == pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt)
+ kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
+
+ pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
+ }
+ }
+ kfree(pstClassifierRulesTable);
+ stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
+ }
+ }
+ }
+
+ kfree(psServiceFlowRulesTable);
+ psServiceFlowRulesTable = NULL;
+}
+
+static bool ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule)
+{
+ if (psPhsRule) {
+ if (!psPhsRule->u8PHSI) {
+ /* PHSI is not valid */
+ return false;
+ }
+
+ if (!psPhsRule->u8PHSS) {
+ /* PHSS Is Undefined */
+ return false;
+ }
+
+ /* Check if PHSF is defines for the PHS Rule */
+ if (!psPhsRule->u8PHSFLength) /* If any part of PHSF is valid then Rule contains valid PHSF */
+ return false;
+
+ return TRUE;
+ } else
+ return false;
+}
+
+UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
+ IN B_UINT16 uiVcid,
+ struct bcm_phs_entry **ppstServiceFlowEntry)
+{
+ int i;
+
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+ if (psServiceFlowTable->stSFList[i].bUsed) {
+ if (psServiceFlowTable->stSFList[i].uiVcid == uiVcid) {
+ *ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
+ return i;
+ }
+ }
+ }
+
+ *ppstServiceFlowEntry = NULL;
+ return PHS_INVALID_TABLE_INDEX;
+}
+
+static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
+ IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
+ OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
+{
+ int i;
+ struct bcm_phs_classifier_entry *psClassifierRules = NULL;
+
+ for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
+
+ if (eClsContext == eActiveClassifierRuleContext)
+ psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
+ else
+ psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
+
+ if (psClassifierRules->bUsed) {
+ if (psClassifierRules->uiClassifierRuleId == uiClsid) {
+ *ppstClassifierEntry = psClassifierRules;
+ return i;
+ }
+ }
+ }
+
+ *ppstClassifierEntry = NULL;
+ return PHS_INVALID_TABLE_INDEX;
+}
+
+static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
+ IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext,
+ OUT struct bcm_phs_rule **ppstPhsRule)
+{
+ int i;
+ struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
+
+ for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
+ if (eClsContext == eActiveClassifierRuleContext)
+ pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
+ else
+ pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
+
+ if (pstClassifierRule->bUsed) {
+ if (pstClassifierRule->u8PHSI == uiPHSI) {
+ *ppstPhsRule = pstClassifierRule->pstPhsRule;
+ return i;
+ }
+ }
+ }
+
+ *ppstPhsRule = NULL;
+ return PHS_INVALID_TABLE_INDEX;
+}
+
+static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16 uiClsId,
+ IN struct bcm_phs_table *psServiceFlowTable,
+ struct bcm_phs_rule *psPhsRule,
+ B_UINT8 u8AssociatedPHSI)
+{
+ struct bcm_phs_classifier_table *psaClassifiertable = NULL;
+ UINT uiStatus = 0;
+ int iSfIndex;
+ bool bFreeEntryFound = false;
+
+ /* Check for a free entry in SFID table */
+ for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
+ if (!psServiceFlowTable->stSFList[iSfIndex].bUsed) {
+ bFreeEntryFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bFreeEntryFound)
+ return ERR_SFTABLE_FULL;
+
+ psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
+ uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable, psPhsRule,
+ eActiveClassifierRuleContext, u8AssociatedPHSI);
+ if (uiStatus == PHS_SUCCESS) {
+ /* Add entry at free index to the SF */
+ psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
+ psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
+ }
+
+ return uiStatus;
+}
+
+static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
+ IN B_UINT16 uiClsId,
+ IN struct bcm_phs_entry *pstServiceFlowEntry,
+ struct bcm_phs_rule *psPhsRule,
+ B_UINT8 u8AssociatedPHSI)
+{
+ struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
+ UINT uiStatus = PHS_SUCCESS;
+ UINT nClassifierIndex = 0;
+ struct bcm_phs_classifier_table *psaClassifiertable = NULL;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
+
+ /* Check if the supplied Classifier already exists */
+ nClassifierIndex = GetClassifierEntry(
+ pstServiceFlowEntry->pstClassifierTable,
+ uiClsId,
+ eActiveClassifierRuleContext,
+ &pstClassifierEntry);
+
+ if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
+ /*
+ * The Classifier doesn't exist. So its a new classifier being added.
+ * Add new entry to associate PHS Rule to the Classifier
+ */
+
+ uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
+ psPhsRule,
+ eActiveClassifierRuleContext,
+ u8AssociatedPHSI);
+ return uiStatus;
+ }
+
+ /*
+ * The Classifier exists.The PHS Rule for this classifier
+ * is being modified
+ */
+
+ if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) {
+ if (pstClassifierEntry->pstPhsRule == NULL)
+ return ERR_PHS_INVALID_PHS_RULE;
+
+ /*
+ * This rule already exists if any fields are changed for this PHS
+ * rule update them.
+ */
+ /* If any part of PHSF is valid then we update PHSF */
+ if (psPhsRule->u8PHSFLength) {
+ /* update PHSF */
+ memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
+ psPhsRule->u8PHSF, MAX_PHS_LENGTHS);
+ }
+
+ if (psPhsRule->u8PHSFLength) {
+ /* update PHSFLen */
+ pstClassifierEntry->pstPhsRule->u8PHSFLength = psPhsRule->u8PHSFLength;
+ }
+
+ if (psPhsRule->u8PHSMLength) {
+ /* update PHSM */
+ memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
+ psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
+ }
+
+ if (psPhsRule->u8PHSMLength) {
+ /* update PHSM Len */
+ pstClassifierEntry->pstPhsRule->u8PHSMLength =
+ psPhsRule->u8PHSMLength;
+ }
+
+ if (psPhsRule->u8PHSS) {
+ /* update PHSS */
+ pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
+ }
+
+ /* update PHSV */
+ pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
+ } else {
+ /* A new rule is being set for this classifier. */
+ uiStatus = UpdateClassifierPHSRule(uiClsId, pstClassifierEntry,
+ psaClassifiertable, psPhsRule, u8AssociatedPHSI);
+ }
+
+ return uiStatus;
+}
+
+static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
+ struct bcm_phs_classifier_table *psaClassifiertable,
+ struct bcm_phs_rule *psPhsRule,
+ enum bcm_phs_classifier_context eClsContext,
+ B_UINT8 u8AssociatedPHSI)
+{
+ UINT iClassifierIndex = 0;
+ bool bFreeEntryFound = false;
+ struct bcm_phs_classifier_entry *psClassifierRules = NULL;
+ UINT nStatus = PHS_SUCCESS;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Inside CreateClassifierPHSRule");
+
+ if (psaClassifiertable == NULL)
+ return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
+
+ if (eClsContext == eOldClassifierRuleContext) {
+ /*
+ * If An Old Entry for this classifier ID already exists in the
+ * old rules table replace it.
+ */
+
+ iClassifierIndex =
+ GetClassifierEntry(psaClassifiertable, uiClsId,
+ eClsContext, &psClassifierRules);
+
+ if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
+ /*
+ * The Classifier already exists in the old rules table
+ * Lets replace the old classifier with the new one.
+ */
+ bFreeEntryFound = TRUE;
+ }
+ }
+
+ if (!bFreeEntryFound) {
+ /* Continue to search for a free location to add the rule */
+ for (iClassifierIndex = 0; iClassifierIndex <
+ MAX_PHSRULE_PER_SF; iClassifierIndex++) {
+ if (eClsContext == eActiveClassifierRuleContext)
+ psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
+ else
+ psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
+
+ if (!psClassifierRules->bUsed) {
+ bFreeEntryFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!bFreeEntryFound) {
+
+ if (eClsContext == eActiveClassifierRuleContext)
+ return ERR_CLSASSIFIER_TABLE_FULL;
+ else {
+ /* Lets replace the oldest rule if we are looking in old Rule table */
+ if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
+ psaClassifiertable->uiOldestPhsRuleIndex = 0;
+
+ iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
+ psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
+
+ (psaClassifiertable->uiOldestPhsRuleIndex)++;
+ }
+ }
+
+ if (eClsContext == eOldClassifierRuleContext) {
+
+ if (psClassifierRules->pstPhsRule == NULL) {
+
+ psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
+
+ if (NULL == psClassifierRules->pstPhsRule)
+ return ERR_PHSRULE_MEMALLOC_FAIL;
+ }
+
+ psClassifierRules->bUsed = TRUE;
+ psClassifierRules->uiClassifierRuleId = uiClsId;
+ psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
+ psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
+
+ /* Update The PHS rule */
+ memcpy(psClassifierRules->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
+ } else
+ nStatus = UpdateClassifierPHSRule(uiClsId, psClassifierRules,
+ psaClassifiertable, psPhsRule, u8AssociatedPHSI);
+
+ return nStatus;
+}
+
+static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
+ IN struct bcm_phs_classifier_entry *pstClassifierEntry,
+ struct bcm_phs_classifier_table *psaClassifiertable,
+ struct bcm_phs_rule *psPhsRule,
+ B_UINT8 u8AssociatedPHSI)
+{
+ struct bcm_phs_rule *pstAddPhsRule = NULL;
+ UINT nPhsRuleIndex = 0;
+ bool bPHSRuleOrphaned = false;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ psPhsRule->u8RefCnt = 0;
+
+ /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
+ bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
+ pstClassifierEntry->pstPhsRule);
+
+ /* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF */
+ nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
+ eActiveClassifierRuleContext, &pstAddPhsRule);
+ if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
+
+ if (psPhsRule->u8PHSI == 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
+ return ERR_PHS_INVALID_PHS_RULE;
+ }
+
+ /* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */
+ if (false == bPHSRuleOrphaned) {
+
+ pstClassifierEntry->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
+ if (NULL == pstClassifierEntry->pstPhsRule)
+ return ERR_PHSRULE_MEMALLOC_FAIL;
+ }
+ memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule));
+ } else {
+ /* Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
+ if (bPHSRuleOrphaned) {
+ kfree(pstClassifierEntry->pstPhsRule);
+ pstClassifierEntry->pstPhsRule = NULL;
+ }
+ pstClassifierEntry->pstPhsRule = pstAddPhsRule;
+ }
+
+ pstClassifierEntry->bUsed = TRUE;
+ pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
+ pstClassifierEntry->uiClassifierRuleId = uiClsId;
+ pstClassifierEntry->pstPhsRule->u8RefCnt++;
+ pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
+
+ return PHS_SUCCESS;
+}
+
+static bool DerefPhsRule(IN B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule)
+{
+ if (pstPhsRule == NULL)
+ return false;
+
+ if (pstPhsRule->u8RefCnt)
+ pstPhsRule->u8RefCnt--;
+
+ if (0 == pstPhsRule->u8RefCnt) {
+ /*
+ * if(pstPhsRule->u8PHSI)
+ * Store the currently active rule into the old rules list
+ * CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);
+ */
+ return TRUE;
+ } else
+ return false;
+}
+
+void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
+{
+ int i, j, k, l;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules :\n");
+
+ for (i = 0; i < MAX_SERVICEFLOWS; i++) {
+
+ struct bcm_phs_entry stServFlowEntry =
+ pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
+ if (stServFlowEntry.bUsed) {
+
+ for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
+
+ for (l = 0; l < 2; l++) {
+ struct bcm_phs_classifier_entry stClsEntry;
+
+ if (l == 0) {
+ stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
+ if (stClsEntry.bUsed)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule :\n");
+ } else {
+ stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
+ if (stClsEntry.bUsed)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule :\n");
+ }
+
+ if (stClsEntry.bUsed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X", stServFlowEntry.uiVcid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X", stClsEntry.uiClassifierRuleId);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X", stClsEntry.u8PHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X", stClsEntry.pstPhsRule->u8PHSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", stClsEntry.pstPhsRule->u8PHSFLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
+
+ for (k = 0 ; k < stClsEntry.pstPhsRule->u8PHSFLength; k++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", stClsEntry.pstPhsRule->u8PHSF[k]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X", stClsEntry.pstPhsRule->u8PHSMLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
+
+ for (k = 0; k < stClsEntry.pstPhsRule->u8PHSMLength; k++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", stClsEntry.pstPhsRule->u8PHSM[k]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", stClsEntry.pstPhsRule->u8PHSS);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X", stClsEntry.pstPhsRule->u8PHSV);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Procedure: phs_decompress
+ *
+ * Description: This routine restores the static fields within the packet.
+ *
+ * Arguments:
+ * in_buf - ptr to incoming packet buffer.
+ * out_buf - ptr to output buffer where the suppressed header is copied.
+ * decomp_phs_rules - ptr to PHS rule.
+ * header_size - ptr to field which holds the phss or phsf_length.
+ *
+ * Returns:
+ * size -The number of bytes of dynamic fields present with in the incoming packet
+ * header.
+ * 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
+ */
+static int phs_decompress(unsigned char *in_buf,
+ unsigned char *out_buf,
+ struct bcm_phs_rule *decomp_phs_rules,
+ UINT *header_size)
+{
+ int phss, size = 0;
+ struct bcm_phs_rule *tmp_memb;
+ int bit, i = 0;
+ unsigned char *phsf, *phsm;
+ int in_buf_len = *header_size - 1;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ in_buf++;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "====>\n");
+ *header_size = 0;
+
+ if ((decomp_phs_rules == NULL))
+ return 0;
+
+ tmp_memb = decomp_phs_rules;
+ /*
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
+ * header_size = tmp_memb->u8PHSFLength;
+ */
+ phss = tmp_memb->u8PHSS;
+ phsf = tmp_memb->u8PHSF;
+ phsm = tmp_memb->u8PHSM;
+
+ if (phss > MAX_PHS_LENGTHS)
+ phss = MAX_PHS_LENGTHS;
+
+ /*
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:
+ * In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
+ */
+ while ((phss > 0) && (size < in_buf_len)) {
+ bit = ((*phsm << i) & SUPPRESS);
+
+ if (bit == SUPPRESS) {
+ *out_buf = *phsf;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss %d phsf %d output %d",
+ phss, *phsf, *out_buf);
+ } else {
+ *out_buf = *in_buf;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss %d input %d output %d",
+ phss, *in_buf, *out_buf);
+ in_buf++;
+ size++;
+ }
+ out_buf++;
+ phsf++;
+ phss--;
+ i++;
+ *header_size = *header_size + 1;
+
+ if (i > MAX_NO_BIT) {
+ i = 0;
+ phsm++;
+ }
+ }
+
+ return size;
+}
+
+/*
+ * Procedure: phs_compress
+ *
+ * Description: This routine suppresses the static fields within the packet.Before
+ * that it will verify the fields to be suppressed with the corresponding fields in the
+ * phsf. For verification it checks the phsv field of PHS rule. If set and verification
+ * succeeds it suppresses the field.If any one static field is found different none of
+ * the static fields are suppressed then the packet is sent as uncompressed packet with
+ * phsi=0.
+ *
+ * Arguments:
+ * phs_rule - ptr to PHS rule.
+ * in_buf - ptr to incoming packet buffer.
+ * out_buf - ptr to output buffer where the suppressed header is copied.
+ * header_size - ptr to field which holds the phss.
+ *
+ * Returns:
+ * size-The number of bytes copied into the output buffer i.e dynamic fields
+ * 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails.
+ */
+static int phs_compress(struct bcm_phs_rule *phs_rule,
+ unsigned char *in_buf,
+ unsigned char *out_buf,
+ UINT *header_size,
+ UINT *new_header_size)
+{
+ unsigned char *old_addr = out_buf;
+ int suppress = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ if (phs_rule == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nphs_compress(): phs_rule null!");
+ *out_buf = ZERO_PHSI;
+ return STATUS_PHS_NOCOMPRESSION;
+ }
+
+ if (phs_rule->u8PHSS <= *new_header_size)
+ *header_size = phs_rule->u8PHSS;
+ else
+ *header_size = *new_header_size;
+
+ /* To copy PHSI */
+ out_buf++;
+ suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF,
+ phs_rule->u8PHSM, phs_rule->u8PHSS,
+ phs_rule->u8PHSV, new_header_size);
+
+ if (suppress == STATUS_PHS_COMPRESSED) {
+ *old_addr = (unsigned char)phs_rule->u8PHSI;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress phsi %d", phs_rule->u8PHSI);
+ } else {
+ *old_addr = ZERO_PHSI;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress PHSV Verification failed");
+ }
+
+ return suppress;
+}
+
+/*
+ * Procedure: verify_suppress_phsf
+ *
+ * Description: This routine verifies the fields of the packet and if all the
+ * static fields are equal it adds the phsi of that PHS rule.If any static
+ * field differs it woun't suppress any field.
+ *
+ * Arguments:
+ * rules_set - ptr to classifier_rules.
+ * in_buffer - ptr to incoming packet buffer.
+ * out_buffer - ptr to output buffer where the suppressed header is copied.
+ * phsf - ptr to phsf.
+ * phsm - ptr to phsm.
+ * phss - variable holding phss.
+ *
+ * Returns:
+ * size-The number of bytes copied into the output buffer i.e dynamic fields.
+ * 0 -Packet has failed the verification.
+ */
+static int verify_suppress_phsf(unsigned char *in_buffer,
+ unsigned char *out_buffer,
+ unsigned char *phsf,
+ unsigned char *phsm,
+ unsigned int phss,
+ unsigned int phsv,
+ UINT *new_header_size)
+{
+ unsigned int size = 0;
+ int bit, i = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
+
+ if (phss > (*new_header_size))
+ phss = *new_header_size;
+
+ while (phss > 0) {
+ bit = ((*phsm << i) & SUPPRESS);
+ if (bit == SUPPRESS) {
+ if (*in_buffer != *phsf) {
+ if (phsv == VERIFY) {
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ PHS_SEND,
+ DBG_LVL_ALL,
+ "\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",
+ phss,
+ *in_buffer,
+ *phsf);
+ return STATUS_PHS_NOCOMPRESSION;
+ }
+ } else
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ PHS_SEND,
+ DBG_LVL_ALL,
+ "\nCOMP:In verify_phsf success for field %d buf %d phsf %d",
+ phss,
+ *in_buffer,
+ *phsf);
+ } else {
+ *out_buffer = *in_buffer;
+ BCM_DEBUG_PRINT(Adapter,
+ DBG_TYPE_OTHERS,
+ PHS_SEND,
+ DBG_LVL_ALL,
+ "\nCOMP:In copying_header input %d out %d",
+ *in_buffer,
+ *out_buffer);
+ out_buffer++;
+ size++;
+ }
+
+ in_buffer++;
+ phsf++;
+ phss--;
+ i++;
+
+ if (i > MAX_NO_BIT) {
+ i = 0;
+ phsm++;
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf success");
+ *new_header_size = size;
+ return STATUS_PHS_COMPRESSED;
+}
diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h
new file mode 100644
index 00000000000..d697f9c860c
--- /dev/null
+++ b/drivers/staging/bcm/PHSModule.h
@@ -0,0 +1,50 @@
+#ifndef BCM_MINIPORT_PHSMODULE_H
+#define BCM_MINIPORT_PHSMODULE_H
+
+int PHSTransmit(struct bcm_mini_adapter *Adapter,
+ struct sk_buff **pPacket,
+ USHORT Vcid,
+ B_UINT16 uiClassifierRuleID,
+ bool bHeaderSuppressionEnabled,
+ PUINT PacketLen,
+ UCHAR bEthCSSupport);
+
+int PHSReceive(struct bcm_mini_adapter *Adapter,
+ USHORT usVcid,
+ struct sk_buff *packet,
+ UINT *punPacketLen,
+ UCHAR *pucEthernetHdr,
+ UINT
+ );
+
+
+void DumpDataPacketHeader(PUCHAR pPkt);
+
+void DumpFullPacket(UCHAR *pBuf,UINT nPktLen);
+
+void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension);
+
+
+int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,struct bcm_mini_adapter *Adapter);
+
+int PhsCleanup(struct bcm_phs_extension *pPHSDeviceExt);
+
+//Utility Functions
+ULONG PhsUpdateClassifierRule(void* pvContext,B_UINT16 uiVcid,B_UINT16 uiClsId, struct bcm_phs_rule *psPhsRule,B_UINT8 u8AssociatedPHSI );
+
+ULONG PhsDeletePHSRule(void* pvContext,B_UINT16 uiVcid,B_UINT8 u8PHSI);
+
+ULONG PhsDeleteClassifierRule(void* pvContext, B_UINT16 uiVcid ,B_UINT16 uiClsId);
+
+ULONG PhsDeleteSFRules(void* pvContext,B_UINT16 uiVcid) ;
+
+
+bool ValidatePHSRule(struct bcm_phs_rule *psPhsRule);
+
+UINT GetServiceFlowEntry(struct bcm_phs_table *psServiceFlowTable,B_UINT16 uiVcid, struct bcm_phs_entry **ppstServiceFlowEntry);
+
+
+void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension);
+
+
+#endif
diff --git a/drivers/staging/bcm/Protocol.h b/drivers/staging/bcm/Protocol.h
new file mode 100644
index 00000000000..9818128d932
--- /dev/null
+++ b/drivers/staging/bcm/Protocol.h
@@ -0,0 +1,128 @@
+/************************************
+* Protocol.h
+*************************************/
+#ifndef __PROTOCOL_H__
+#define __PROTOCOL_H__
+
+#define IPV4 4
+#define IPV6 6
+
+struct ArpHeader {
+ struct arphdr arp;
+ unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
+ unsigned char ar_sip[4]; /* sender IP address */
+ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
+ unsigned char ar_tip[4]; /* target IP address */
+};
+
+struct bcm_transport_header {
+ union {
+ struct udphdr uhdr;
+ struct tcphdr thdr;
+ };
+} __packed;
+
+enum bcm_ip_frame_type {
+ eNonIPPacket,
+ eIPv4Packet,
+ eIPv6Packet
+};
+
+enum bcm_eth_frame_type {
+ eEthUnsupportedFrame,
+ eEth802LLCFrame,
+ eEth802LLCSNAPFrame,
+ eEth802QVLANFrame,
+ eEthOtherFrame
+};
+
+struct bcm_eth_packet_info {
+ enum bcm_ip_frame_type eNwpktIPFrameType;
+ enum bcm_eth_frame_type eNwpktEthFrameType;
+ unsigned short usEtherType;
+ unsigned char ucDSAP;
+};
+
+struct bcm_eth_q_frame {
+ struct bcm_eth_header EThHdr;
+ unsigned short UserPriority:3;
+ unsigned short CFI:1;
+ unsigned short VLANID:12;
+ unsigned short EthType;
+} __packed;
+
+struct bcm_eth_llc_frame {
+ struct bcm_eth_header EThHdr;
+ unsigned char DSAP;
+ unsigned char SSAP;
+ unsigned char Control;
+} __packed;
+
+struct bcm_eth_llc_snap_frame {
+ struct bcm_eth_header EThHdr;
+ unsigned char DSAP;
+ unsigned char SSAP;
+ unsigned char Control;
+ unsigned char OUI[3];
+ unsigned short usEtherType;
+} __packed;
+
+struct bcm_ethernet2_frame {
+ struct bcm_eth_header EThHdr;
+} __packed;
+
+#define ETHERNET_FRAMETYPE_IPV4 ntohs(0x0800)
+#define ETHERNET_FRAMETYPE_IPV6 ntohs(0x86dd)
+#define ETHERNET_FRAMETYPE_802QVLAN ntohs(0x8100)
+
+/* Per SF CS Specification Encodings */
+enum bcm_spec_encoding {
+ eCSSpecUnspecified = 0,
+ eCSPacketIPV4,
+ eCSPacketIPV6,
+ eCS802_3PacketEthernet,
+ eCS802_1QPacketVLAN,
+ eCSPacketIPV4Over802_3Ethernet,
+ eCSPacketIPV6Over802_3Ethernet,
+ eCSPacketIPV4Over802_1QVLAN,
+ eCSPacketIPV6Over802_1QVLAN,
+ eCSPacketUnsupported
+};
+
+#define IP6_HEADER_LEN 40
+#define IP_VERSION(byte) (((byte&0xF0)>>4))
+
+#define MAC_ADDRESS_SIZE 6
+#define ETH_AND_IP_HEADER_LEN (14 + 20)
+#define L4_SRC_PORT_LEN 2
+#define L4_DEST_PORT_LEN 2
+#define CTRL_PKT_LEN (8 + ETH_AND_IP_HEADER_LEN)
+
+#define ETH_ARP_FRAME 0x806
+#define ETH_IPV4_FRAME 0x800
+#define ETH_IPV6_FRAME 0x86DD
+#define UDP 0x11
+#define TCP 0x06
+
+#define ARP_OP_REQUEST 0x01
+#define ARP_OP_REPLY 0x02
+#define ARP_PKT_SIZE 60
+
+/* This is the format for the TCP packet header */
+struct bcm_tcp_header {
+ unsigned short usSrcPort;
+ unsigned short usDestPort;
+ unsigned long ulSeqNumber;
+ unsigned long ulAckNumber;
+ unsigned char HeaderLength;
+ unsigned char ucFlags;
+ unsigned short usWindowsSize;
+ unsigned short usChkSum;
+ unsigned short usUrgetPtr;
+};
+
+#define TCP_HEADER_LEN sizeof(struct bcm_tcp_header)
+#define TCP_ACK 0x10 /* Bit 4 in tcpflags field. */
+#define GET_TCP_HEADER_LEN(byte) ((byte&0xF0)>>4)
+
+#endif /* __PROTOCOL_H__ */
diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h
new file mode 100644
index 00000000000..fb53a00591e
--- /dev/null
+++ b/drivers/staging/bcm/Prototypes.h
@@ -0,0 +1,222 @@
+#ifndef _PROTOTYPES_H_
+#define _PROTOTYPES_H_
+
+VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer);
+
+VOID StatisticsResponse(struct bcm_mini_adapter *Adapter,PVOID pvBuffer);
+
+VOID IdleModeResponse(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
+
+int control_packet_handler (struct bcm_mini_adapter *Adapter);
+
+VOID DeleteAllClassifiersForSF(struct bcm_mini_adapter *Adapter,UINT uiSearchRuleIndex);
+
+VOID flush_all_queues(struct bcm_mini_adapter *Adapter);
+
+int register_control_device_interface(struct bcm_mini_adapter *ps_adapter);
+
+void unregister_control_device_interface(struct bcm_mini_adapter *Adapter);
+
+INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
+ PVOID ioBuffer/**<Control Packet Buffer*/
+ );
+
+VOID SortPackInfo(struct bcm_mini_adapter *Adapter);
+
+VOID SortClassifiers(struct bcm_mini_adapter *Adapter);
+
+VOID flush_all_queues(struct bcm_mini_adapter *Adapter);
+
+VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter);
+
+INT SearchSfid(struct bcm_mini_adapter *Adapter,UINT uiSfid);
+
+USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb);
+
+bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort);
+bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort);
+bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol);
+
+
+INT SetupNextSend(struct bcm_mini_adapter *Adapter, /**<Logical Adapter*/
+ struct sk_buff *Packet, /**<data buffer*/
+ USHORT Vcid) ;
+
+VOID LinkMessage(struct bcm_mini_adapter *Adapter);
+
+VOID transmit_packets(struct bcm_mini_adapter *Adapter);
+
+INT SendControlPacket(struct bcm_mini_adapter *Adapter, /**<Logical Adapter*/
+ char *pControlPacket/**<Control Packet*/
+ );
+
+
+int register_networkdev(struct bcm_mini_adapter *Adapter);
+void unregister_networkdev(struct bcm_mini_adapter *Adapter);
+
+INT AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
+
+VOID AdapterFree(struct bcm_mini_adapter *Adapter);
+
+INT FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
+
+int tx_pkt_handler(struct bcm_mini_adapter *Adapter);
+
+int reset_card_proc(struct bcm_mini_adapter *Adapter );
+
+int run_card_proc(struct bcm_mini_adapter *Adapter );
+
+int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter);
+
+
+INT ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter);
+
+int register_control_device_interface(struct bcm_mini_adapter *ps_adapter);
+
+void DumpPackInfo(struct bcm_mini_adapter *Adapter);
+
+int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
+
+int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
+
+int wrmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+
+int rdmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+
+int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId, void __user * user_buffer);
+
+void SendIdleModeResponse(struct bcm_mini_adapter *Adapter);
+
+
+int ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_mibs *buf);
+void GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *ioBuffer, struct bcm_tarang_data *pTarang);
+void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter);
+
+int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo);
+
+void CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter,
+ struct bcm_connect_mgr_params *psfLocalSet, UINT uiSearchRuleIndex);
+
+VOID ResetCounters(struct bcm_mini_adapter *Adapter);
+
+int InitLedSettings(struct bcm_mini_adapter *Adapter);
+
+struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter,USHORT usIpIdentification,ULONG SrcIP);
+
+void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo);
+
+void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter,USHORT usIpIdentification,ULONG SrcIp);
+
+void update_per_cid_rx (struct bcm_mini_adapter *Adapter);
+
+void update_per_sf_desc_cnts( struct bcm_mini_adapter *Adapter);
+
+void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter,B_UINT16 TID,bool bFreeAll);
+
+
+void flush_queue(struct bcm_mini_adapter *Adapter, UINT iQIndex);
+
+
+INT flushAllAppQ(VOID);
+
+
+INT BeceemEEPROMBulkRead(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ UINT uiOffset,
+ UINT uiNumBytes);
+
+
+
+INT WriteBeceemEEPROM(struct bcm_mini_adapter *Adapter,UINT uiEEPROMOffset, UINT uiData);
+
+INT PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter);
+
+
+INT BeceemEEPROMBulkWrite(
+ struct bcm_mini_adapter *Adapter,
+ PUCHAR pBuffer,
+ UINT uiOffset,
+ UINT uiNumBytes,
+ bool bVerify);
+
+
+INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter,UINT dwAddress, UINT *pdwData);
+
+
+INT BeceemNVMRead(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ UINT uiOffset,
+ UINT uiNumBytes);
+
+INT BeceemNVMWrite(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ UINT uiOffset,
+ UINT uiNumBytes,
+ bool bVerify);
+
+
+INT BcmInitNVM(struct bcm_mini_adapter *Adapter);
+
+INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize);
+bool IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
+
+INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap);
+
+INT BcmFlash2xBulkWrite(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ enum bcm_flash2x_section_val eFlashSectionVal,
+ UINT uiOffset,
+ UINT uiNumBytes,
+ UINT bVerify);
+
+INT BcmFlash2xBulkRead(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ enum bcm_flash2x_section_val eFlashSectionVal,
+ UINT uiOffsetWithinSectionVal,
+ UINT uiNumBytes);
+
+INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal);
+
+INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal);
+INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter);
+INT BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter);
+
+INT BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut);
+INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal);
+INT validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite);
+INT IsFlash2x(struct bcm_mini_adapter *Adapter);
+INT BcmCopySection(struct bcm_mini_adapter *Adapter,
+ enum bcm_flash2x_section_val SrcSection,
+ enum bcm_flash2x_section_val DstSection,
+ UINT offset,
+ UINT numOfBytes);
+
+
+bool IsNonCDLessDevice(struct bcm_mini_adapter *Adapter);
+
+
+VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
+
+int wrmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+int rdmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+
+int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
+INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
+ unsigned long u32StartingAddress);
+
+
+VOID putUsbSuspend(struct work_struct *work);
+bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios);
+
+
+#endif
+
+
+
+
diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c
new file mode 100644
index 00000000000..0c742da8c6b
--- /dev/null
+++ b/drivers/staging/bcm/Qos.c
@@ -0,0 +1,777 @@
+/**
+@file Qos.C
+This file contains the routines related to Quality of Service.
+*/
+#include "headers.h"
+
+static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,
+ PVOID pvEthPayload,
+ struct bcm_eth_packet_info *pstEthCsPktInfo);
+
+static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,
+ struct sk_buff *skb,
+ struct bcm_eth_packet_info *pstEthCsPktInfo,
+ struct bcm_classifier_rule *pstClassifierRule,
+ B_UINT8 EthCSCupport);
+
+static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd,
+ struct bcm_classifier_rule *pstClassifierRule);
+
+static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex);
+
+
+/*******************************************************************
+* Function - MatchSrcIpAddress()
+*
+* Description - Checks whether the Source IP address from the packet
+* matches with that of Queue.
+*
+* Parameters - pstClassifierRule: Pointer to the packet info structure.
+* - ulSrcIP : Source IP address from the packet.
+*
+* Returns - TRUE(If address matches) else FAIL .
+*********************************************************************/
+static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulSrcIP)
+{
+ UCHAR ucLoopIndex = 0;
+
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ ulSrcIP = ntohl(ulSrcIP);
+ if (0 == pstClassifierRule->ucIPSourceAddressLength)
+ return TRUE;
+ for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); ucLoopIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]);
+ if ((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
+ (pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]))
+ return TRUE;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
+ return false;
+}
+
+
+/*******************************************************************
+* Function - MatchDestIpAddress()
+*
+* Description - Checks whether the Destination IP address from the packet
+* matches with that of Queue.
+*
+* Parameters - pstClassifierRule: Pointer to the packet info structure.
+* - ulDestIP : Destination IP address from the packet.
+*
+* Returns - TRUE(If address matches) else FAIL .
+*********************************************************************/
+static bool MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP)
+{
+ UCHAR ucLoopIndex = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ ulDestIP = ntohl(ulDestIP);
+ if (0 == pstClassifierRule->ucIPDestinationAddressLength)
+ return TRUE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]);
+
+ for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); ucLoopIndex++) {
+ if ((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP) ==
+ (pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex]))
+ return TRUE;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
+ return false;
+}
+
+
+/************************************************************************
+* Function - MatchTos()
+*
+* Description - Checks the TOS from the packet matches with that of queue.
+*
+* Parameters - pstClassifierRule : Pointer to the packet info structure.
+* - ucTypeOfService: TOS from the packet.
+*
+* Returns - TRUE(If address matches) else FAIL.
+**************************************************************************/
+static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucTypeOfService)
+{
+
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if (3 != pstClassifierRule->ucIPTypeOfServiceLength)
+ return TRUE;
+
+ if (((pstClassifierRule->ucTosMask & ucTypeOfService) <= pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService) >= pstClassifierRule->ucTosLow))
+ return TRUE;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
+ return false;
+}
+
+
+/***************************************************************************
+* Function - MatchProtocol()
+*
+* Description - Checks the protocol from the packet matches with that of queue.
+*
+* Parameters - pstClassifierRule: Pointer to the packet info structure.
+* - ucProtocol : Protocol from the packet.
+*
+* Returns - TRUE(If address matches) else FAIL.
+****************************************************************************/
+bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucProtocol)
+{
+ UCHAR ucLoopIndex = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if (0 == pstClassifierRule->ucProtocolLength)
+ return TRUE;
+ for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucProtocolLength; ucLoopIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X", ucProtocol, pstClassifierRule->ucProtocol[ucLoopIndex]);
+ if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol)
+ return TRUE;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
+ return false;
+}
+
+
+/***********************************************************************
+* Function - MatchSrcPort()
+*
+* Description - Checks, Source port from the packet matches with that of queue.
+*
+* Parameters - pstClassifierRule: Pointer to the packet info structure.
+* - ushSrcPort : Source port from the packet.
+*
+* Returns - TRUE(If address matches) else FAIL.
+***************************************************************************/
+bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPort)
+{
+ UCHAR ucLoopIndex = 0;
+
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+
+ if (0 == pstClassifierRule->ucSrcPortRangeLength)
+ return TRUE;
+ for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; ucLoopIndex++) {
+ if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
+ ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
+ return TRUE;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ", ushSrcPort);
+ return false;
+}
+
+
+/***********************************************************************
+* Function - MatchDestPort()
+*
+* Description - Checks, Destination port from packet matches with that of queue.
+*
+* Parameters - pstClassifierRule: Pointer to the packet info structure.
+* - ushDestPort : Destination port from the packet.
+*
+* Returns - TRUE(If address matches) else FAIL.
+***************************************************************************/
+bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushDestPort)
+{
+ UCHAR ucLoopIndex = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ if (0 == pstClassifierRule->ucDestPortRangeLength)
+ return TRUE;
+
+ for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; ucLoopIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X 0x%X 0x%X", ushDestPort, pstClassifierRule->usDestPortRangeLo[ucLoopIndex], pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
+
+ if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
+ ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
+ return TRUE;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched", ushDestPort);
+ return false;
+}
+/**
+@ingroup tx_functions
+Compares IPV4 Ip address and port number
+@return Queue Index.
+*/
+static USHORT IpVersion4(struct bcm_mini_adapter *Adapter,
+ struct iphdr *iphd,
+ struct bcm_classifier_rule *pstClassifierRule)
+{
+ struct bcm_transport_header *xprt_hdr = NULL;
+ bool bClassificationSucceed = false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>");
+
+ xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr));
+
+ do {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d",
+ pstClassifierRule->ucDirection,
+ pstClassifierRule->usVCID_Value);
+
+ //Checking classifier validity
+ if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
+ break;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
+ if (pstClassifierRule->bIpv6Protocol)
+ break;
+
+ //**************Checking IP header parameter**************************//
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
+ if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
+ break;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
+
+ if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
+ break;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
+
+ if (!MatchTos(pstClassifierRule, iphd->tos)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
+ break;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
+
+ if (!MatchProtocol(pstClassifierRule, iphd->protocol))
+ break;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
+
+ //if protocol is not TCP or UDP then no need of comparing source port and destination port
+ if (iphd->protocol != TCP && iphd->protocol != UDP) {
+ bClassificationSucceed = TRUE;
+ break;
+ }
+ //******************Checking Transport Layer Header field if present *****************//
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
+ (iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
+
+ if (!MatchSrcPort(pstClassifierRule,
+ ntohs((iphd->protocol == UDP) ?
+ xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
+ break;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
+ (iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
+ xprt_hdr->thdr.dest);
+ if (!MatchDestPort(pstClassifierRule,
+ ntohs((iphd->protocol == UDP) ?
+ xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
+ break;
+ bClassificationSucceed = TRUE;
+ } while (0);
+
+ if (TRUE == bClassificationSucceed) {
+ INT iMatchedSFQueueIndex = 0;
+ iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+ if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
+ bClassificationSucceed = false;
+ else if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
+ bClassificationSucceed = false;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <==========");
+
+ return bClassificationSucceed;
+}
+
+VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter)
+{
+ UINT iIndex = 0;
+
+ for (iIndex = 0; iIndex < HiPriority; iIndex++) {
+ if (!Adapter->PackInfo[iIndex].bValid)
+ continue;
+
+ PruneQueue(Adapter, iIndex);
+ }
+}
+
+
+/**
+@ingroup tx_functions
+This function checks if the max queue size for a queue
+is less than number of bytes in the queue. If so -
+drops packets from the Head till the number of bytes is
+less than or equal to max queue size for the queue.
+*/
+static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
+{
+ struct sk_buff* PacketToDrop = NULL;
+ struct net_device_stats *netstats;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d", iIndex);
+
+ if (iIndex == HiPriority)
+ return;
+
+ if (!Adapter || (iIndex < 0) || (iIndex > HiPriority))
+ return;
+
+ /* To Store the netdevice statistic */
+ netstats = &Adapter->dev->stats;
+
+ spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
+
+ while (1) {
+// while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
+// SF_MAX_ALLOWED_PACKETS_TO_BACKUP) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
+ Adapter->PackInfo[iIndex].uiCurrentBytesOnHost,
+ Adapter->PackInfo[iIndex].uiMaxBucketSize);
+
+ PacketToDrop = Adapter->PackInfo[iIndex].FirstTxQueue;
+
+ if (PacketToDrop == NULL)
+ break;
+ if ((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) &&
+ ((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb)+SKB_CB_LATENCY_OFFSET))/HZ) <= Adapter->PackInfo[iIndex].uiMaxLatency))
+ break;
+
+ if (PacketToDrop) {
+ if (netif_msg_tx_err(Adapter))
+ pr_info(PFX "%s: tx queue %d overlimit\n",
+ Adapter->dev->name, iIndex);
+
+ netstats->tx_dropped++;
+
+ DEQUEUEPACKET(Adapter->PackInfo[iIndex].FirstTxQueue,
+ Adapter->PackInfo[iIndex].LastTxQueue);
+ /// update current bytes and packets count
+ Adapter->PackInfo[iIndex].uiCurrentBytesOnHost -=
+ PacketToDrop->len;
+ Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost--;
+ /// update dropped bytes and packets counts
+ Adapter->PackInfo[iIndex].uiDroppedCountBytes += PacketToDrop->len;
+ Adapter->PackInfo[iIndex].uiDroppedCountPackets++;
+ dev_kfree_skb(PacketToDrop);
+
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
+ Adapter->PackInfo[iIndex].uiDroppedCountBytes,
+ Adapter->PackInfo[iIndex].uiDroppedCountPackets);
+
+ atomic_dec(&Adapter->TotalPacketCount);
+ }
+
+ spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x",
+ atomic_read(&Adapter->TotalPacketCount));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<=====");
+}
+
+VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
+{
+ INT iQIndex;
+ UINT uiTotalPacketLength;
+ struct sk_buff* PacketToDrop = NULL;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>");
+
+// down(&Adapter->data_packet_queue_lock);
+ for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++) {
+ struct net_device_stats *netstats = &Adapter->dev->stats;
+
+ spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
+ while (Adapter->PackInfo[iQIndex].FirstTxQueue) {
+ PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
+ if (PacketToDrop) {
+ uiTotalPacketLength = PacketToDrop->len;
+ netstats->tx_dropped++;
+ } else
+ uiTotalPacketLength = 0;
+
+ DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue,
+ Adapter->PackInfo[iQIndex].LastTxQueue);
+
+ /* Free the skb */
+ dev_kfree_skb(PacketToDrop);
+
+ /// update current bytes and packets count
+ Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= uiTotalPacketLength;
+ Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
+
+ /// update dropped bytes and packets counts
+ Adapter->PackInfo[iQIndex].uiDroppedCountBytes += uiTotalPacketLength;
+ Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x",
+ Adapter->PackInfo[iQIndex].uiDroppedCountBytes,
+ Adapter->PackInfo[iQIndex].uiDroppedCountPackets);
+ atomic_dec(&Adapter->TotalPacketCount);
+ }
+ spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
+ }
+// up(&Adapter->data_packet_queue_lock);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<=====");
+}
+
+USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
+{
+ INT uiLoopIndex = 0;
+ struct bcm_classifier_rule *pstClassifierRule = NULL;
+ struct bcm_eth_packet_info stEthCsPktInfo;
+ PVOID pvEThPayload = NULL;
+ struct iphdr *pIpHeader = NULL;
+ INT uiSfIndex = 0;
+ USHORT usIndex = Adapter->usBestEffortQueueIndex;
+ bool bFragmentedPkt = false, bClassificationSucceed = false;
+ USHORT usCurrFragment = 0;
+
+ struct bcm_tcp_header *pTcpHeader;
+ UCHAR IpHeaderLength;
+ UCHAR TcpHeaderLength;
+
+ pvEThPayload = skb->data;
+ *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET) = 0;
+ EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo);
+
+ switch (stEthCsPktInfo.eNwpktEthFrameType) {
+ case eEth802LLCFrame:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n");
+ pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame);
+ break;
+ case eEth802LLCSNAPFrame:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n");
+ pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_snap_frame);
+ break;
+ case eEth802QVLANFrame:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n");
+ pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame);
+ break;
+ case eEthOtherFrame:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n");
+ pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n");
+ pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
+ break;
+ }
+
+ if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) {
+ usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET);
+ if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
+ bFragmentedPkt = TRUE;
+
+ if (bFragmentedPkt) {
+ //Fragmented Packet. Get Frag Classifier Entry.
+ pstClassifierRule = GetFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
+ if (pstClassifierRule) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "It is next Fragmented pkt");
+ bClassificationSucceed = TRUE;
+ }
+ if (!(ntohs(pIpHeader->frag_off) & IP_MF)) {
+ //Fragmented Last packet . Remove Frag Classifier Entry
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "This is the last fragmented Pkt");
+ DelFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
+ }
+ }
+ }
+
+ for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) {
+ if (bClassificationSucceed)
+ break;
+ //Iterate through all classifiers which are already in order of priority
+ //to classify the packet until match found
+ do {
+ if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) {
+ bClassificationSucceed = false;
+ break;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex);
+
+ if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) {
+ bClassificationSucceed = false;//cannot be processed for classification.
+ break; // it is a down link connection
+ }
+
+ pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex];
+
+ uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+ if (uiSfIndex >= NO_OF_QUEUES) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Queue Not Valid. SearchSfid for this classifier Failed\n");
+ break;
+ }
+
+ if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) {
+
+ if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
+ bClassificationSucceed = false;
+ break;
+ }
+
+
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", pstClassifierRule->uiClassifierRuleIndex, Adapter->PackInfo[uiSfIndex].ulSFID);
+ bClassificationSucceed = EThCSClassifyPkt(Adapter, skb, &stEthCsPktInfo, pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport);
+
+ if (!bClassificationSucceed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Ethernet CS Classification Failed\n");
+ break;
+ }
+ } else { // No ETH Supported on this SF
+ if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
+ bClassificationSucceed = false;
+ break;
+ }
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Proceeding to IP CS Clasification");
+
+ if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) {
+
+ if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n");
+ bClassificationSucceed = false;
+ break;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header :\n");
+ DumpFullPacket((PUCHAR)pIpHeader, 20);
+
+ if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
+ bClassificationSucceed = IpVersion4(Adapter, pIpHeader, pstClassifierRule);
+ else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet)
+ bClassificationSucceed = IpVersion6(Adapter, pIpHeader, pstClassifierRule);
+ }
+
+ } while (0);
+ }
+
+ if (bClassificationSucceed == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu", pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
+
+ //Store The matched Classifier in SKB
+ *((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex;
+ if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len)) {
+ IpHeaderLength = pIpHeader->ihl;
+ pTcpHeader = (struct bcm_tcp_header *)(((PUCHAR)pIpHeader)+(IpHeaderLength*4));
+ TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
+
+ if ((pTcpHeader->ucFlags & TCP_ACK) &&
+ (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4)))
+ *((UINT32*) (skb->cb) + SKB_CB_TCPACK_OFFSET) = TCP_ACK;
+ }
+
+ usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is =%d", usIndex);
+
+ //If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt.
+ if (bFragmentedPkt && (usCurrFragment == 0)) {
+ //First Fragment of Fragmented Packet. Create Frag CLS Entry
+ struct bcm_fragmented_packet_info stFragPktInfo;
+ stFragPktInfo.bUsed = TRUE;
+ stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr;
+ stFragPktInfo.usIpIdentification = pIpHeader->id;
+ stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule;
+ stFragPktInfo.bOutOfOrderFragment = false;
+ AddFragIPClsEntry(Adapter, &stFragPktInfo);
+ }
+
+
+ }
+
+ if (bClassificationSucceed)
+ return usIndex;
+ else
+ return INVALID_QUEUE_INDEX;
+}
+
+static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
+{
+ UINT i = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if (pstClassifierRule->ucEthCSSrcMACLen == 0)
+ return TRUE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __func__);
+ for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]);
+ if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) !=
+ (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
+ return false;
+ }
+ return TRUE;
+}
+
+static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
+{
+ UINT i = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if (pstClassifierRule->ucEthCSDestMACLen == 0)
+ return TRUE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __func__);
+ for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]);
+ if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) !=
+ (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
+ return false;
+ }
+ return TRUE;
+}
+
+static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if ((pstClassifierRule->ucEtherTypeLen == 0) ||
+ (pstClassifierRule->au8EthCSEtherType[0] == 0))
+ return TRUE;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __func__, pstEthCsPktInfo->usEtherType, pstClassifierRule->au8EthCSEtherType[0]);
+ if (pstClassifierRule->au8EthCSEtherType[0] == 1) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS EtherType[1]:%x EtherType[2]:%x\n", __func__, pstClassifierRule->au8EthCSEtherType[1], pstClassifierRule->au8EthCSEtherType[2]);
+
+ if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0)
+ return TRUE;
+ else
+ return false;
+ }
+
+ if (pstClassifierRule->au8EthCSEtherType[0] == 2) {
+ if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
+ return false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s EthCS DSAP:%x EtherType[2]:%x\n", __func__, pstEthCsPktInfo->ucDSAP, pstClassifierRule->au8EthCSEtherType[2]);
+ if (pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2])
+ return TRUE;
+ else
+ return false;
+
+ }
+
+ return false;
+
+}
+
+static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+{
+ bool bClassificationSucceed = false;
+ USHORT usVLANID;
+ B_UINT8 uPriority = 0;
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n", __func__, ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), pstClassifierRule->usVLANID);
+
+ /* In case FW didn't receive the TLV, the priority field should be ignored */
+ if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) {
+ if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
+ return false;
+
+ uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13;
+
+ if ((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1]))
+ bClassificationSucceed = TRUE;
+
+ if (!bClassificationSucceed)
+ return false;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 D User Priority Rule Matched\n");
+
+ bClassificationSucceed = false;
+
+ if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID)) {
+ if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
+ return false;
+
+ usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n", __func__, usVLANID, uPriority);
+
+ if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4))
+ bClassificationSucceed = TRUE;
+
+ if (!bClassificationSucceed)
+ return false;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 Q VLAN ID Rule Matched\n");
+
+ return TRUE;
+}
+
+
+static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb,
+ struct bcm_eth_packet_info *pstEthCsPktInfo,
+ struct bcm_classifier_rule *pstClassifierRule,
+ B_UINT8 EthCSCupport)
+{
+ bool bClassificationSucceed = false;
+ bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
+ if (!bClassificationSucceed)
+ return false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS SrcMAC Matched\n");
+
+ bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
+ if (!bClassificationSucceed)
+ return false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS DestMAC Matched\n");
+
+ //classify on ETHType/802.2SAP TLV
+ bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, skb, pstEthCsPktInfo);
+ if (!bClassificationSucceed)
+ return false;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS EthType/802.2SAP Matched\n");
+
+ //classify on 802.1VLAN Header Parameters
+
+ bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, skb, pstEthCsPktInfo);
+ if (!bClassificationSucceed)
+ return false;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 VLAN Rules Matched\n");
+
+ return bClassificationSucceed;
+}
+
+static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload,
+ struct bcm_eth_packet_info *pstEthCsPktInfo)
+{
+ USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype);
+ if (u16Etype > 0x5dc) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame\n");
+ //ETH2 Frame
+ if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) {
+ //802.1Q VLAN Header
+ pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
+ u16Etype = ((struct bcm_eth_q_frame *)pvEthPayload)->EthType;
+ //((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority
+ } else {
+ pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame;
+ u16Etype = ntohs(u16Etype);
+ }
+ } else {
+ //802.2 LLC
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame\n");
+ pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame;
+ pstEthCsPktInfo->ucDSAP = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
+ if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) {
+ //SNAP Frame
+ pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
+ u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType;
+ }
+ }
+ if (u16Etype == ETHERNET_FRAMETYPE_IPV4)
+ pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet;
+ else if (u16Etype == ETHERNET_FRAMETYPE_IPV6)
+ pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet;
+ else
+ pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket;
+
+ pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo->eNwpktIPFrameType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo->eNwpktEthFrameType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo->usEtherType);
+}
+
+
+
diff --git a/drivers/staging/bcm/Queue.h b/drivers/staging/bcm/Queue.h
new file mode 100644
index 00000000000..e1f1da2bb6d
--- /dev/null
+++ b/drivers/staging/bcm/Queue.h
@@ -0,0 +1,31 @@
+/*************************************
+* Queue.h
+**************************************/
+#ifndef __QUEUE_H__
+#define __QUEUE_H__
+
+
+
+#define ENQUEUEPACKET(_Head, _Tail,_Packet) \
+do \
+{ \
+ if (!_Head) { \
+ _Head = _Packet; \
+ } \
+ else { \
+ (_Tail)->next = _Packet; \
+ } \
+ (_Packet)->next = NULL; \
+ _Tail = _Packet; \
+}while(0)
+#define DEQUEUEPACKET(Head, Tail ) \
+do \
+{ if(Head) \
+ { \
+ if (!Head->next) { \
+ Tail = NULL; \
+ } \
+ Head = Head->next; \
+ } \
+}while(0)
+#endif //__QUEUE_H__
diff --git a/drivers/staging/bcm/TODO b/drivers/staging/bcm/TODO
new file mode 100644
index 00000000000..cd3e9f2ed87
--- /dev/null
+++ b/drivers/staging/bcm/TODO
@@ -0,0 +1,22 @@
+This driver is barely functional in its current state.
+
+BIG:
+ - existing API is (/dev/tarang) should be replaced
+ Is it possible to use same API as Intel Wimax stack and
+ have same user level components.
+ - Qos and queue model is non-standard and inflexible.
+ Use existing TC Qos?
+
+TODO:
+ - support more than one board - eliminate global variables
+ - remove developer debug BCM_DEBUG() macros
+ add a limited number of messages through netif_msg()
+ - fix non-standard kernel style
+ - checkpatch warnings
+ - use request firmware
+ - fix use of file I/O to load config with better API
+ - merge some files together?
+ - cleanup/eliminate debug messages
+
+
+
diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c
new file mode 100644
index 00000000000..49767468ac2
--- /dev/null
+++ b/drivers/staging/bcm/Transmit.c
@@ -0,0 +1,245 @@
+/**
+ * @file Transmit.c
+ * @defgroup tx_functions Transmission
+ * @section Queueing
+ * @dot
+ * digraph transmit1 {
+ * node[shape=box]
+ * edge[weight=5;color=red]
+ *
+ * bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
+ * GetPacketQueueIndex->IpVersion4[label="IPV4"]
+ * GetPacketQueueIndex->IpVersion6[label="IPV6"]
+ * }
+ *
+ * @enddot
+ *
+ * @section De-Queueing
+ * @dot
+ * digraph transmit2 {
+ * node[shape=box]
+ * edge[weight=5;color=red]
+ * interrupt_service_thread->transmit_packets
+ * tx_pkt_hdler->transmit_packets
+ * transmit_packets->CheckAndSendPacketFromIndex
+ * transmit_packets->UpdateTokenCount
+ * CheckAndSendPacketFromIndex->PruneQueue
+ * CheckAndSendPacketFromIndex->IsPacketAllowedForFlow
+ * CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"]
+ * SendControlPacket->bcm_cmd53
+ * CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"]
+ * SendPacketFromQueue->SetupNextSend->bcm_cmd53
+ * }
+ * @enddot
+ */
+
+#include "headers.h"
+
+/**
+ * @ingroup ctrl_pkt_functions
+ * This function dispatches control packet to the h/w interface
+ * @return zero(success) or -ve value(failure)
+ */
+int SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket)
+{
+ struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
+ if (!pControlPacket || !Adapter) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
+ "Got NULL Control Packet or Adapter");
+ return STATUS_FAILURE;
+ }
+ if ((atomic_read(&Adapter->CurrNumFreeTxDesc) <
+ ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
+ "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
+ return STATUS_FAILURE;
+ }
+
+ /* Update the netdevice statistics */
+ /* Dump Packet */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x", PLeader->Vcid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x", PLeader->PLength);
+ if (Adapter->device_removed)
+ return 0;
+
+ if (netif_msg_pktdata(Adapter))
+ print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
+ 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0);
+
+ Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
+ pControlPacket, (PLeader->PLength + LEADER_SIZE));
+
+ atomic_dec(&Adapter->CurrNumFreeTxDesc);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @ingroup tx_functions
+ * This function despatches the IP packets with the given vcid
+ * to the target via the host h/w interface.
+ * @return zero(success) or -ve value(failure)
+ */
+int SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid)
+{
+ int status = 0;
+ bool bHeaderSupressionEnabled = false;
+ B_UINT16 uiClassifierRuleID;
+ u16 QueueIndex = skb_get_queue_mapping(Packet);
+ struct bcm_leader Leader = {0};
+
+ if (Packet->len > MAX_DEVICE_DESC_SIZE) {
+ status = STATUS_FAILURE;
+ goto errExit;
+ }
+
+ /* Get the Classifier Rule ID */
+ uiClassifierRuleID = *((UINT32 *) (Packet->cb) + SKB_CB_CLASSIFICATION_OFFSET);
+
+ bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
+ & Adapter->bPHSEnabled;
+
+ if (Adapter->device_removed) {
+ status = STATUS_FAILURE;
+ goto errExit;
+ }
+
+ status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
+ (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
+
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
+ "PHS Transmit failed..\n");
+ goto errExit;
+ }
+
+ Leader.Vcid = Vcid;
+
+ if (TCP_ACK == *((UINT32 *) (Packet->cb) + SKB_CB_TCPACK_OFFSET))
+ Leader.Status = LEADER_STATUS_TCP_ACK;
+ else
+ Leader.Status = LEADER_STATUS;
+
+ if (Adapter->PackInfo[QueueIndex].bEthCSSupport) {
+ Leader.PLength = Packet->len;
+ if (skb_headroom(Packet) < LEADER_SIZE) {
+ status = skb_cow(Packet, LEADER_SIZE);
+ if (status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit : Failed To Increase headRoom\n");
+ goto errExit;
+ }
+ }
+ skb_push(Packet, LEADER_SIZE);
+ memcpy(Packet->data, &Leader, LEADER_SIZE);
+ } else {
+ Leader.PLength = Packet->len - ETH_HLEN;
+ memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
+ }
+
+ status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
+ Packet->data, (Leader.PLength + LEADER_SIZE));
+ if (status) {
+ ++Adapter->dev->stats.tx_errors;
+ if (netif_msg_tx_err(Adapter))
+ pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
+ status);
+ } else {
+ struct net_device_stats *netstats = &Adapter->dev->stats;
+ Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
+
+ netstats->tx_bytes += Leader.PLength;
+ ++netstats->tx_packets;
+
+ Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
+ Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
+ Adapter->PackInfo[QueueIndex].uiSentPackets++;
+ Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
+
+ atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
+ Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
+ }
+
+ atomic_dec(&Adapter->CurrNumFreeTxDesc);
+
+errExit:
+ dev_kfree_skb(Packet);
+ return status;
+}
+
+static int tx_pending(struct bcm_mini_adapter *Adapter)
+{
+ return (atomic_read(&Adapter->TxPktAvail)
+ && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
+ || Adapter->device_removed || (1 == Adapter->downloadDDR);
+}
+
+/**
+ * @ingroup tx_functions
+ * Transmit thread
+ */
+int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/)
+{
+ int status = 0;
+
+ while (!kthread_should_stop()) {
+ /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
+ if (Adapter->LinkUpStatus)
+ wait_event_timeout(Adapter->tx_packet_wait_queue,
+ tx_pending(Adapter), msecs_to_jiffies(10));
+ else
+ wait_event_interruptible(Adapter->tx_packet_wait_queue,
+ tx_pending(Adapter));
+
+ if (Adapter->device_removed)
+ break;
+
+ if (Adapter->downloadDDR == 1) {
+ Adapter->downloadDDR += 1;
+ status = download_ddr_settings(Adapter);
+ if (status)
+ pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
+ continue;
+ }
+
+ /* Check end point for halt/stall. */
+ if (Adapter->bEndPointHalted == TRUE) {
+ Bcm_clear_halt_of_endpoints(Adapter);
+ Adapter->bEndPointHalted = false;
+ StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
+ }
+
+ if (Adapter->LinkUpStatus && !Adapter->IdleMode) {
+ if (atomic_read(&Adapter->TotalPacketCount))
+ update_per_sf_desc_cnts(Adapter);
+ }
+
+ if (atomic_read(&Adapter->CurrNumFreeTxDesc) &&
+ Adapter->LinkStatus == SYNC_UP_REQUEST &&
+ !Adapter->bSyncUpRequestSent) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
+ DBG_LVL_ALL, "Calling LinkMessage");
+ LinkMessage(Adapter);
+ }
+
+ if ((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
+ TX_PACKETS, DBG_LVL_ALL,
+ "Device in Low Power mode...waking up");
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ }
+
+ transmit_packets(Adapter);
+ atomic_set(&Adapter->TxPktAvail, 0);
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
+ "Exiting the tx thread..\n");
+ Adapter->transmit_packet_thread = NULL;
+ return 0;
+}
diff --git a/drivers/staging/bcm/Typedefs.h b/drivers/staging/bcm/Typedefs.h
new file mode 100644
index 00000000000..90b3b25dd60
--- /dev/null
+++ b/drivers/staging/bcm/Typedefs.h
@@ -0,0 +1,47 @@
+/****************************
+* Typedefs.h
+****************************/
+#ifndef __TYPEDEFS_H__
+#define __TYPEDEFS_H__
+#define STATUS_SUCCESS 0
+#define STATUS_FAILURE -1
+
+
+#define TRUE 1
+
+
+typedef char CHAR;
+typedef int INT;
+typedef short SHORT;
+typedef long LONG;
+typedef void VOID;
+
+typedef unsigned char UCHAR;
+typedef unsigned char B_UINT8;
+typedef unsigned short USHORT;
+typedef unsigned short B_UINT16;
+typedef unsigned int UINT;
+typedef unsigned int B_UINT32;
+typedef unsigned long ULONG;
+typedef unsigned long DWORD;
+
+typedef char *PCHAR;
+typedef short *PSHORT;
+typedef int *PINT;
+typedef long *PLONG;
+typedef void *PVOID;
+
+typedef unsigned char *PUCHAR;
+typedef unsigned short *PUSHORT;
+typedef unsigned int *PUINT;
+typedef unsigned long *PULONG;
+typedef unsigned long long ULONG64;
+typedef unsigned long long LARGE_INTEGER;
+typedef unsigned int UINT32;
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+#endif /* __TYPEDEFS_H__ */
+
diff --git a/drivers/staging/bcm/cntrl_SignalingInterface.h b/drivers/staging/bcm/cntrl_SignalingInterface.h
new file mode 100644
index 00000000000..8683c2d4276
--- /dev/null
+++ b/drivers/staging/bcm/cntrl_SignalingInterface.h
@@ -0,0 +1,311 @@
+#ifndef CNTRL_SIGNALING_INTERFACE_
+#define CNTRL_SIGNALING_INTERFACE_
+
+#define DSA_REQ 11
+#define DSA_RSP 12
+#define DSA_ACK 13
+#define DSC_REQ 14
+#define DSC_RSP 15
+#define DSC_ACK 16
+#define DSD_REQ 17
+#define DSD_RSP 18
+#define DSD_ACK 19
+#define MAX_CLASSIFIERS_IN_SF 4
+
+#define MAX_STRING_LEN 20
+#define MAX_PHS_LENGTHS 255
+#define VENDOR_PHS_PARAM_LENGTH 10
+#define MAX_NUM_ACTIVE_BS 10
+#define AUTH_TOKEN_LENGTH 10
+#define NUM_HARQ_CHANNELS 16 /* Changed from 10 to 16 to accommodate all HARQ channels */
+#define VENDOR_CLASSIFIER_PARAM_LENGTH 1 /* Changed the size to 1 byte since we dnt use it */
+#define VENDOR_SPECIF_QOS_PARAM 1
+#define VENDOR_PHS_PARAM_LENGTH 10
+#define MBS_CONTENTS_ID_LENGTH 10
+#define GLOBAL_SF_CLASSNAME_LENGTH 6
+
+#define TYPE_OF_SERVICE_LENGTH 3
+#define IP_MASKED_SRC_ADDRESS_LENGTH 32
+#define IP_MASKED_DEST_ADDRESS_LENGTH 32
+#define PROTOCOL_SRC_PORT_RANGE_LENGTH 4
+#define PROTOCOL_DEST_PORT_RANGE_LENGTH 4
+#define ETHERNET_DEST_MAC_ADDR_LENGTH 12
+#define ETHERNET_SRC_MAC_ADDR_LENGTH 12
+#define NUM_ETHERTYPE_BYTES 3
+#define NUM_IPV6_FLOWLABLE_BYTES 3
+
+struct bcm_packet_class_rules {
+ /* 16bit UserPriority Of The Service Flow */
+ u16 u16UserPriority;
+ /* 16bit VLANID Of The Service Flow */
+ u16 u16VLANID;
+ /* 16bit Packet Classification RuleIndex Of The Service Flow */
+ u16 u16PacketClassificationRuleIndex;
+ /* 8bit Classifier Rule Priority Of The Service Flow */
+ u8 u8ClassifierRulePriority;
+ /* Length of IP TypeOfService field */
+ u8 u8IPTypeOfServiceLength;
+ /* 3bytes IP TypeOfService */
+ u8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH];
+ /* Protocol used in classification of Service Flow */
+ u8 u8Protocol;
+ /* Length of IP Masked Source Address */
+ u8 u8IPMaskedSourceAddressLength;
+ /* IP Masked Source Address used in classification for the Service Flow */
+ u8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH];
+ /* Length of IP Destination Address */
+ u8 u8IPDestinationAddressLength;
+ /* IP Destination Address used in classification for the Service Flow */
+ u8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH];
+ /* Length of Protocol Source Port Range */
+ u8 u8ProtocolSourcePortRangeLength;
+ /* Protocol Source Port Range used in the Service Flow */
+ u8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH];
+ /* Length of Protocol Dest Port Range */
+ u8 u8ProtocolDestPortRangeLength;
+ /* Protocol Dest Port Range used in the Service Flow */
+ u8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH];
+ /* Length of Ethernet Destination MAC Address */
+ u8 u8EthernetDestMacAddressLength;
+ /* Ethernet Destination MAC Address used in classification of the Service Flow */
+ u8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH];
+ /* Length of Ethernet Source MAC Address */
+ u8 u8EthernetSourceMACAddressLength;
+ /* Ethernet Source MAC Address used in classification of the Service Flow */
+ u8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH];
+ /* Length of Ethertype */
+ u8 u8EthertypeLength;
+ /* 3bytes Ethertype Of The Service Flow */
+ u8 u8Ethertype[NUM_ETHERTYPE_BYTES];
+ /* 8bit Associated PHSI Of The Service Flow */
+ u8 u8AssociatedPHSI;
+ /* Length of Vendor Specific Classifier Param length Of The Service Flow */
+ u8 u8VendorSpecificClassifierParamLength;
+ /* Vendor Specific Classifier Param Of The Service Flow */
+ u8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH];
+ /* Length Of IPv6 Flow Lable of the Service Flow */
+ u8 u8IPv6FlowLableLength;
+ /* IPv6 Flow Lable Of The Service Flow */
+ u8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES];
+ /* Action associated with the classifier rule */
+ u8 u8ClassifierActionRule;
+ u16 u16ValidityBitMap;
+};
+
+struct bcm_phs_rules {
+ /* 8bit PHS Index Of The Service Flow */
+ u8 u8PHSI;
+ /* PHSF Length Of The Service Flow */
+ u8 u8PHSFLength;
+ /* String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS */
+ u8 u8PHSF[MAX_PHS_LENGTHS];
+ /* PHSM Length Of The Service Flow */
+ u8 u8PHSMLength;
+ /* PHS Mask for the SF */
+ u8 u8PHSM[MAX_PHS_LENGTHS];
+ /* 8bit Total number of bytes to be suppressed for the Service Flow */
+ u8 u8PHSS;
+ /* 8bit Indicates whether or not Packet Header contents need to be verified prior to suppression */
+ u8 u8PHSV;
+ /* Vendor Specific PHS param Length Of The Service Flow */
+ u8 u8VendorSpecificPHSParamsLength;
+ /* Vendor Specific PHS param Of The Service Flow */
+ u8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH];
+ u8 u8Padding[2];
+};
+
+struct bcm_convergence_types {
+ /* 8bit Phs Classfier Action Of The Service Flow */
+ u8 u8ClassfierDSCAction;
+ /* 8bit Phs DSC Action Of The Service Flow */
+ u8 u8PhsDSCAction;
+ /* 16bit Padding */
+ u8 u8Padding[2];
+ /* Packet classification rules structure */
+ struct bcm_packet_class_rules cCPacketClassificationRule;
+ /* Payload header suppression rules structure */
+ struct bcm_phs_rules cPhsRule;
+};
+
+struct bcm_connect_mgr_params {
+ /* 32bitSFID Of The Service Flow */
+ u32 u32SFID;
+ /* 32bit Maximum Sustained Traffic Rate of the Service Flow */
+ u32 u32MaxSustainedTrafficRate;
+ /* 32bit Maximum Traffic Burst allowed for the Service Flow */
+ u32 u32MaxTrafficBurst;
+ /* 32bit Minimum Reserved Traffic Rate of the Service Flow */
+ u32 u32MinReservedTrafficRate;
+ /* 32bit Tolerated Jitter of the Service Flow */
+ u32 u32ToleratedJitter;
+ /* 32bit Maximum Latency of the Service Flow */
+ u32 u32MaximumLatency;
+ /* 16bitCID Of The Service Flow */
+ u16 u16CID;
+ /* 16bit SAID on which the service flow being set up shall be mapped */
+ u16 u16TargetSAID;
+ /* 16bit ARQ window size negotiated */
+ u16 u16ARQWindowSize;
+ /* 16bit Total Tx delay incl sending, receiving & processing delays */
+ u16 u16ARQRetryTxTimeOut;
+ /* 16bit Total Rx delay incl sending, receiving & processing delays */
+ u16 u16ARQRetryRxTimeOut;
+ /* 16bit ARQ block lifetime */
+ u16 u16ARQBlockLifeTime;
+ /* 16bit ARQ Sync loss timeout */
+ u16 u16ARQSyncLossTimeOut;
+ /* 16bit ARQ Purge timeout */
+ u16 u16ARQRxPurgeTimeOut;
+ /* TODO::Remove this once we move to a new CORR2 driver
+ * brief Size of an ARQ block
+ */
+ u16 u16ARQBlockSize;
+ /* #endif */
+ /* 16bit Nominal interval b/w consecutive SDU arrivals at MAC SAP */
+ u16 u16SDUInterArrivalTime;
+ /* 16bit Specifies the time base for rate measurement */
+ u16 u16TimeBase;
+ /* 16bit Interval b/w Successive Grant oppurtunities */
+ u16 u16UnsolicitedGrantInterval;
+ /* 16bit Interval b/w Successive Polling grant oppurtunities */
+ u16 u16UnsolicitedPollingInterval;
+ /* internal var to get the overhead */
+ u16 u16MacOverhead;
+ /* MBS contents Identifier */
+ u16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH];
+ /* MBS contents Identifier length */
+ u8 u8MBSContentsIDLength;
+ /* ServiceClassName Length Of The Service Flow */
+ u8 u8ServiceClassNameLength;
+ /* 32bytes ServiceClassName Of The Service Flow */
+ u8 u8ServiceClassName[32];
+ /* 8bit Indicates whether or not MBS service is requested for this Serivce Flow */
+ u8 u8MBSService;
+ /* 8bit QOS Parameter Set specifies proper application of QoS parameters to Provisioned, Admitted and Active sets */
+ u8 u8QosParamSet;
+ /* 8bit Traffic Priority Of the Service Flow */
+ u8 u8TrafficPriority;
+ /* 8bit Uplink Grant Scheduling Type of The Service Flow */
+ u8 u8ServiceFlowSchedulingType;
+ /* 8bit Request transmission Policy of the Service Flow */
+ u8 u8RequesttransmissionPolicy;
+ /* 8bit Specifies whether SDUs for this Service flow are of FixedLength or Variable length */
+ u8 u8FixedLengthVSVariableLengthSDUIndicator;
+ /* 8bit Length of the SDU for a fixed length SDU service flow */
+ u8 u8SDUSize;
+ /* 8bit Indicates whether or not ARQ is requested for this connection */
+ u8 u8ARQEnable;
+ /* < 8bit Indicates whether or not data has tobe delivered in order to higher layer */
+ u8 u8ARQDeliverInOrder;
+ /* 8bit Receiver ARQ ACK processing time */
+ u8 u8RxARQAckProcessingTime;
+ /* 8bit Convergence Sublayer Specification Of The Service Flow */
+ u8 u8CSSpecification;
+ /* 8 bit Type of data delivery service */
+ u8 u8TypeOfDataDeliveryService;
+ /* 8bit Specifies whether a service flow may generate Paging */
+ u8 u8PagingPreference;
+ /* 8bit Indicates the MBS Zone through which the connection or virtual connection is valid */
+ u8 u8MBSZoneIdentifierassignment;
+ /* 8bit Specifies whether traffic on SF should generate MOB_TRF_IND to MS in sleep mode */
+ u8 u8TrafficIndicationPreference;
+ /* 8bit Speciifes the length of predefined Global QoS parameter set encoding for this SF */
+ u8 u8GlobalServicesClassNameLength;
+ /* 6 byte Speciifes the predefined Global QoS parameter set encoding for this SF */
+ u8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH];
+ /* 8bit Indicates whether or not SN feedback is enabled for the conn */
+ u8 u8SNFeedbackEnabled;
+ /* Indicates the size of the Fragment Sequence Number for the connection */
+ u8 u8FSNSize;
+ /* 8bit Number of CIDs in active BS list */
+ u8 u8CIDAllocation4activeBSsLength;
+ /* CIDs of BS in the active list */
+ u8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS];
+ /* Specifies if PDU extended subheader should be applied on every PDU on this conn */
+ u8 u8PDUSNExtendedSubheader4HarqReordering;
+ /* 8bit Specifies whether the connection uses HARQ or not */
+ u8 u8HARQServiceFlows;
+ /* Specifies the length of Authorization token */
+ u8 u8AuthTokenLength;
+ /* Specifies the Authorization token */
+ u8 u8AuthToken[AUTH_TOKEN_LENGTH];
+ /* specifes Number of HARQ channels used to carry data length */
+ u8 u8HarqChannelMappingLength;
+ /* specifes HARQ channels used to carry data */
+ u8 u8HARQChannelMapping[NUM_HARQ_CHANNELS];
+ /* 8bit Length of Vendor Specific QoS Params */
+ u8 u8VendorSpecificQoSParamLength;
+ /* 1byte Vendor Specific QoS Param Of The Service Flow */
+ u8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM];
+ /* indicates total classifiers in the SF */
+ u8 u8TotalClassifiers; /* < Total number of valid classifiers */
+ u8 bValid; /* < Validity flag */
+ u8 u8Padding; /* < Padding byte */
+ /*
+ * Structure for Convergence SubLayer Types with a maximum of 4 classifiers
+ */
+ struct bcm_convergence_types cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF];
+};
+
+struct bcm_add_request {
+ u8 u8Type; /* < Type */
+ u8 eConnectionDir; /* < Connection direction */
+ /* brief 16 bit TID */
+ u16 u16TID; /* < 16bit TID */
+ /* brief 16bitCID */
+ u16 u16CID; /* < 16bit CID */
+ /* brief 16bitVCID */
+ u16 u16VCID; /* < 16bit VCID */
+ struct bcm_connect_mgr_params *psfParameterSet; /* < connection manager parameters */
+};
+
+struct bcm_add_indication {
+ u8 u8Type; /* < Type */
+ u8 eConnectionDir; /* < Connection Direction */
+ /* brief 16 bit TID */
+ u16 u16TID; /* < TID */
+ /* brief 16bitCID */
+ u16 u16CID; /* < 16bitCID */
+ /* brief 16bitVCID */
+ u16 u16VCID; /* < 16bitVCID */
+ struct bcm_connect_mgr_params *psfAuthorizedSet; /* Authorized set of connection manager parameters */
+ struct bcm_connect_mgr_params *psfAdmittedSet; /* Admitted set of connection manager parameters */
+ struct bcm_connect_mgr_params *psfActiveSet; /* Activeset of connection manager parameters */
+ u8 u8CC; /* <Confirmation Code */
+ u8 u8Padd; /* < 8-bit Padding */
+ u16 u16Padd; /* < 16 bit Padding */
+};
+
+struct bcm_del_request {
+ u8 u8Type; /* < Type */
+ u8 u8Padding; /* < Padding byte */
+ u16 u16TID; /* < TID */
+ /* brief 32bitSFID */
+ u32 u32SFID; /* < SFID */
+};
+
+struct bcm_del_indication {
+ u8 u8Type; /* < Type */
+ u8 u8Padding; /* < Padding */
+ u16 u16TID; /* < TID */
+ /* brief 16bitCID */
+ u16 u16CID; /* < CID */
+ /* brief 16bitVCID */
+ u16 u16VCID; /* < VCID */
+ /* brief 32bitSFID */
+ u32 u32SFID; /* < SFID */
+ /* brief 8bit Confirmation code */
+ u8 u8ConfirmationCode; /* < Confirmation code */
+ u8 u8Padding1[3]; /* < 3 byte Padding */
+};
+
+struct bcm_stim_sfhostnotify {
+ u32 SFID; /* SFID of the service flow */
+ u16 newCID; /* the new/changed CID */
+ u16 VCID; /* Get new Vcid if the flow has been made active in CID update TLV, but was inactive earlier or the orig vcid */
+ u8 RetainSF; /* Indication to Host if the SF is to be retained or deleted; if TRUE-retain else delete */
+ u8 QoSParamSet; /* QoS paramset of the retained SF */
+ u16 u16reserved; /* For byte alignment */
+};
+
+#endif
diff --git a/drivers/staging/bcm/headers.h b/drivers/staging/bcm/headers.h
new file mode 100644
index 00000000000..6f3270cc417
--- /dev/null
+++ b/drivers/staging/bcm/headers.h
@@ -0,0 +1,78 @@
+
+/*******************************************************************
+* Headers.h
+*******************************************************************/
+#ifndef __HEADERS_H__
+#define __HEADERS_H__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+#include <linux/wait.h>
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include <linux/stddef.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/unistd.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/kthread.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/usb.h>
+#include <linux/uaccess.h>
+#include <net/ip.h>
+
+#include "Typedefs.h"
+#include "Macros.h"
+#include "HostMIBSInterface.h"
+#include "cntrl_SignalingInterface.h"
+#include "PHSDefines.h"
+#include "led_control.h"
+#include "Ioctl.h"
+#include "nvm.h"
+#include "target_params.h"
+#include "Adapter.h"
+#include "CmHost.h"
+#include "DDRInit.h"
+#include "Debug.h"
+#include "IPv6ProtocolHdr.h"
+#include "PHSModule.h"
+#include "Protocol.h"
+#include "Prototypes.h"
+#include "Queue.h"
+#include "vendorspecificextn.h"
+
+#include "InterfaceMacros.h"
+#include "InterfaceAdapter.h"
+#include "InterfaceIsr.h"
+#include "InterfaceMisc.h"
+#include "InterfaceRx.h"
+#include "InterfaceTx.h"
+#include "InterfaceIdleMode.h"
+#include "InterfaceInit.h"
+
+#define DRV_NAME "beceem"
+#define DEV_NAME "tarang"
+#define DRV_DESCRIPTION "Beceem Communications Inc. WiMAX driver"
+#define DRV_COPYRIGHT "Copyright 2010. Beceem Communications Inc"
+#define DRV_VERSION "5.2.45"
+#define PFX DRV_NAME " "
+
+extern struct class *bcm_class;
+
+#endif
diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c
new file mode 100644
index 00000000000..42d9004e357
--- /dev/null
+++ b/drivers/staging/bcm/hostmibs.c
@@ -0,0 +1,150 @@
+/*
+ * File Name: hostmibs.c
+ *
+ * Author: Beceem Communications Pvt. Ltd
+ *
+ * Abstract: This file contains the routines to copy the statistics used by
+ * the driver to the Host MIBS structure and giving the same to Application.
+ */
+
+#include "headers.h"
+
+INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter,
+ struct bcm_host_stats_mibs *pstHostMibs)
+{
+ struct bcm_phs_entry *pstServiceFlowEntry = NULL;
+ struct bcm_phs_rule *pstPhsRule = NULL;
+ struct bcm_phs_classifier_table *pstClassifierTable = NULL;
+ struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
+ struct bcm_phs_extension *pDeviceExtension = &Adapter->stBCMPhsContext;
+ UINT nClassifierIndex = 0;
+ UINT nPhsTableIndex = 0;
+ UINT nSfIndex = 0;
+ UINT uiIndex = 0;
+
+ if (pDeviceExtension == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, HOST_MIBS,
+ DBG_LVL_ALL, "Invalid Device Extension\n");
+ return STATUS_FAILURE;
+ }
+
+ /* Copy the classifier Table */
+ for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS;
+ nClassifierIndex++) {
+ if (Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE)
+ memcpy(&pstHostMibs->astClassifierTable[nClassifierIndex],
+ &Adapter->astClassifierTable[nClassifierIndex],
+ sizeof(struct bcm_mibs_classifier_rule));
+ }
+
+ /* Copy the SF Table */
+ for (nSfIndex = 0; nSfIndex < NO_OF_QUEUES; nSfIndex++) {
+ if (Adapter->PackInfo[nSfIndex].bValid) {
+ memcpy(&pstHostMibs->astSFtable[nSfIndex],
+ &Adapter->PackInfo[nSfIndex],
+ sizeof(struct bcm_mibs_table));
+ } else {
+ /* If index in not valid,
+ * don't process this for the PHS table.
+ * Go For the next entry.
+ */
+ continue;
+ }
+
+ /* Retrieve the SFID Entry Index for requested Service Flow */
+ if (PHS_INVALID_TABLE_INDEX ==
+ GetServiceFlowEntry(pDeviceExtension->
+ pstServiceFlowPhsRulesTable,
+ Adapter->PackInfo[nSfIndex].
+ usVCID_Value, &pstServiceFlowEntry))
+
+ continue;
+
+ pstClassifierTable = pstServiceFlowEntry->pstClassifierTable;
+
+ for (uiIndex = 0; uiIndex < MAX_PHSRULE_PER_SF; uiIndex++) {
+ pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[uiIndex];
+
+ if (pstClassifierRule->bUsed) {
+ pstPhsRule = pstClassifierRule->pstPhsRule;
+
+ pstHostMibs->astPhsRulesTable[nPhsTableIndex].
+ ulSFID = Adapter->PackInfo[nSfIndex].ulSFID;
+
+ memcpy(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI,
+ &pstPhsRule->u8PHSI,
+ sizeof(struct bcm_phs_rule));
+ nPhsTableIndex++;
+
+ }
+
+ }
+
+ }
+
+ /* Copy other Host Statistics parameters */
+ pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets;
+ pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets;
+ pstHostMibs->stHostInfo.CurrNumFreeDesc =
+ atomic_read(&Adapter->CurrNumFreeTxDesc);
+ pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize;
+ pstHostMibs->stHostInfo.rtPSBucketSize = Adapter->rtPSBucketSize;
+ pstHostMibs->stHostInfo.TimerActive = Adapter->TimerActive;
+ pstHostMibs->stHostInfo.u32TotalDSD = Adapter->u32TotalDSD;
+
+ memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist, Adapter->aTxPktSizeHist,
+ sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
+ memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist, Adapter->aRxPktSizeHist,
+ sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
+
+ return STATUS_SUCCESS;
+}
+
+VOID GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *pstHostMibs,
+ struct bcm_tarang_data *pTarang)
+{
+ memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs),
+ &(pTarang->stDroppedAppCntrlMsgs),
+ sizeof(struct bcm_mibs_dropped_cntrl_msg));
+}
+
+VOID CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter,
+ struct bcm_connect_mgr_params *psfLocalSet,
+ UINT uiSearchRuleIndex)
+{
+ struct bcm_mibs_parameters *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
+
+ t->wmanIfSfid = psfLocalSet->u32SFID;
+ t->wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate;
+ t->wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst;
+ t->wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate;
+ t->wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter;
+ t->wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency;
+ t->wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator;
+ t->wmanIfCmnCpsFixedVsVariableSduInd = ntohl(t->wmanIfCmnCpsFixedVsVariableSduInd);
+ t->wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize;
+ t->wmanIfCmnCpsSduSize = ntohl(t->wmanIfCmnCpsSduSize);
+ t->wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType;
+ t->wmanIfCmnCpsSfSchedulingType = ntohl(t->wmanIfCmnCpsSfSchedulingType);
+ t->wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable;
+ t->wmanIfCmnCpsArqEnable = ntohl(t->wmanIfCmnCpsArqEnable);
+ t->wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize);
+ t->wmanIfCmnCpsArqWindowSize = ntohl(t->wmanIfCmnCpsArqWindowSize);
+ t->wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime);
+ t->wmanIfCmnCpsArqBlockLifetime = ntohl(t->wmanIfCmnCpsArqBlockLifetime);
+ t->wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut);
+ t->wmanIfCmnCpsArqSyncLossTimeout = ntohl(t->wmanIfCmnCpsArqSyncLossTimeout);
+ t->wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder;
+ t->wmanIfCmnCpsArqDeliverInOrder = ntohl(t->wmanIfCmnCpsArqDeliverInOrder);
+ t->wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut);
+ t->wmanIfCmnCpsArqRxPurgeTimeout = ntohl(t->wmanIfCmnCpsArqRxPurgeTimeout);
+ t->wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize);
+ t->wmanIfCmnCpsArqBlockSize = ntohl(t->wmanIfCmnCpsArqBlockSize);
+ t->wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy;
+ t->wmanIfCmnCpsReqTxPolicy = ntohl(t->wmanIfCmnCpsReqTxPolicy);
+ t->wmanIfCmnSfCsSpecification = psfLocalSet->u8CSSpecification;
+ t->wmanIfCmnSfCsSpecification = ntohl(t->wmanIfCmnSfCsSpecification);
+ t->wmanIfCmnCpsTargetSaid = ntohs(psfLocalSet->u16TargetSAID);
+ t->wmanIfCmnCpsTargetSaid = ntohl(t->wmanIfCmnCpsTargetSaid);
+
+}
diff --git a/drivers/staging/bcm/led_control.c b/drivers/staging/bcm/led_control.c
new file mode 100644
index 00000000000..eee4f4795a7
--- /dev/null
+++ b/drivers/staging/bcm/led_control.c
@@ -0,0 +1,916 @@
+#include "headers.h"
+
+#define STATUS_IMAGE_CHECKSUM_MISMATCH -199
+#define EVENT_SIGNALED 1
+
+static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
+{
+ B_UINT16 u16CheckSum = 0;
+ while (u32Size--) {
+ u16CheckSum += (B_UINT8)~(*pu8Buffer);
+ pu8Buffer++;
+ }
+ return u16CheckSum;
+}
+
+bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios)
+{
+ INT Status;
+ Status = (Adapter->gpioBitMap & gpios) ^ gpios;
+ if (Status)
+ return false;
+ else
+ return TRUE;
+}
+
+static INT LED_Blink(struct bcm_mini_adapter *Adapter, UINT GPIO_Num, UCHAR uiLedIndex,
+ ULONG timeout, INT num_of_time, enum bcm_led_events currdriverstate)
+{
+ int Status = STATUS_SUCCESS;
+ bool bInfinite = false;
+
+ /* Check if num_of_time is -ve. If yes, blink led in infinite loop */
+ if (num_of_time < 0) {
+ bInfinite = TRUE;
+ num_of_time = 1;
+ }
+ while (num_of_time) {
+ if (currdriverstate == Adapter->DriverState)
+ TURN_ON_LED(GPIO_Num, uiLedIndex);
+
+ /* Wait for timeout after setting on the LED */
+ Status = wait_event_interruptible_timeout(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState ||
+ kthread_should_stop(),
+ msecs_to_jiffies(timeout));
+
+ if (kthread_should_stop()) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "Led thread got signal to exit..hence exiting");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ TURN_OFF_LED(GPIO_Num, uiLedIndex);
+ Status = EVENT_SIGNALED;
+ break;
+ }
+ if (Status) {
+ TURN_OFF_LED(GPIO_Num, uiLedIndex);
+ Status = EVENT_SIGNALED;
+ break;
+ }
+
+ TURN_OFF_LED(GPIO_Num, uiLedIndex);
+ Status = wait_event_interruptible_timeout(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState ||
+ kthread_should_stop(),
+ msecs_to_jiffies(timeout));
+ if (bInfinite == false)
+ num_of_time--;
+ }
+ return Status;
+}
+
+static INT ScaleRateofTransfer(ULONG rate)
+{
+ if (rate <= 3)
+ return rate;
+ else if ((rate > 3) && (rate <= 100))
+ return 5;
+ else if ((rate > 100) && (rate <= 200))
+ return 6;
+ else if ((rate > 200) && (rate <= 300))
+ return 7;
+ else if ((rate > 300) && (rate <= 400))
+ return 8;
+ else if ((rate > 400) && (rate <= 500))
+ return 9;
+ else if ((rate > 500) && (rate <= 600))
+ return 10;
+ else
+ return MAX_NUM_OF_BLINKS;
+}
+
+
+
+static INT LED_Proportional_Blink(struct bcm_mini_adapter *Adapter, UCHAR GPIO_Num_tx,
+ UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex,
+ enum bcm_led_events currdriverstate)
+{
+ /* Initial values of TX and RX packets */
+ ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
+ /* values of TX and RX packets after 1 sec */
+ ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0;
+ /* Rate of transfer of Tx and Rx in 1 sec */
+ ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0;
+ int Status = STATUS_SUCCESS;
+ INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
+ UINT remDelay = 0;
+ bool bBlinkBothLED = TRUE;
+ /* UINT GPIO_num = DISABLE_GPIO_NUM; */
+ ulong timeout = 0;
+
+ /* Read initial value of packets sent/received */
+ Initial_num_of_packts_tx = Adapter->dev->stats.tx_packets;
+ Initial_num_of_packts_rx = Adapter->dev->stats.rx_packets;
+
+ /* Scale the rate of transfer to no of blinks. */
+ num_of_time_tx = ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
+ num_of_time_rx = ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
+
+ while ((Adapter->device_removed == false)) {
+ timeout = 50;
+ /*
+ * Blink Tx and Rx LED when both Tx and Rx is
+ * in normal bandwidth
+ */
+ if (bBlinkBothLED) {
+ /*
+ * Assign minimum number of blinks of
+ * either Tx or Rx.
+ */
+ if (num_of_time_tx > num_of_time_rx)
+ num_of_time = num_of_time_rx;
+ else
+ num_of_time = num_of_time_tx;
+ if (num_of_time > 0) {
+ /* Blink both Tx and Rx LEDs */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
+ uiTxLedIndex, timeout,
+ num_of_time, currdriverstate)
+ == EVENT_SIGNALED)
+ return EVENT_SIGNALED;
+
+ if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
+ uiRxLedIndex, timeout,
+ num_of_time, currdriverstate)
+ == EVENT_SIGNALED)
+ return EVENT_SIGNALED;
+
+ }
+
+ if (num_of_time == num_of_time_tx) {
+ /* Blink pending rate of Rx */
+ if (LED_Blink(Adapter, (1 << GPIO_Num_rx),
+ uiRxLedIndex, timeout,
+ num_of_time_rx-num_of_time,
+ currdriverstate)
+ == EVENT_SIGNALED)
+ return EVENT_SIGNALED;
+
+ num_of_time = num_of_time_rx;
+ } else {
+ /* Blink pending rate of Tx */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
+ uiTxLedIndex, timeout,
+ num_of_time_tx-num_of_time,
+ currdriverstate)
+ == EVENT_SIGNALED)
+ return EVENT_SIGNALED;
+
+ num_of_time = num_of_time_tx;
+ }
+ } else {
+ if (num_of_time == num_of_time_tx) {
+ /* Blink pending rate of Rx */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_tx,
+ uiTxLedIndex, timeout,
+ num_of_time, currdriverstate)
+ == EVENT_SIGNALED)
+ return EVENT_SIGNALED;
+ } else {
+ /* Blink pending rate of Tx */
+ if (LED_Blink(Adapter, 1 << GPIO_Num_rx,
+ uiRxLedIndex, timeout,
+ num_of_time, currdriverstate)
+ == EVENT_SIGNALED)
+ return EVENT_SIGNALED;
+ }
+ }
+
+ /*
+ * If Tx/Rx rate is less than maximum blinks per second,
+ * wait till delay completes to 1 second
+ */
+ remDelay = MAX_NUM_OF_BLINKS - num_of_time;
+ if (remDelay > 0) {
+ timeout = 100 * remDelay;
+ Status = wait_event_interruptible_timeout(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState
+ || kthread_should_stop(),
+ msecs_to_jiffies(timeout));
+
+ if (kthread_should_stop()) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ LED_DUMP_INFO, DBG_LVL_ALL,
+ "Led thread got signal to exit..hence exiting");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ return EVENT_SIGNALED;
+ }
+ if (Status)
+ return EVENT_SIGNALED;
+ }
+
+ /* Turn off both Tx and Rx LEDs before next second */
+ TURN_OFF_LED(1 << GPIO_Num_tx, uiTxLedIndex);
+ TURN_OFF_LED(1 << GPIO_Num_rx, uiTxLedIndex);
+
+ /*
+ * Read the Tx & Rx packets transmission after 1 second and
+ * calculate rate of transfer
+ */
+ Final_num_of_packts_tx = Adapter->dev->stats.tx_packets;
+ Final_num_of_packts_rx = Adapter->dev->stats.rx_packets;
+
+ rate_of_transfer_tx = Final_num_of_packts_tx -
+ Initial_num_of_packts_tx;
+ rate_of_transfer_rx = Final_num_of_packts_rx -
+ Initial_num_of_packts_rx;
+
+ /* Read initial value of packets sent/received */
+ Initial_num_of_packts_tx = Final_num_of_packts_tx;
+ Initial_num_of_packts_rx = Final_num_of_packts_rx;
+
+ /* Scale the rate of transfer to no of blinks. */
+ num_of_time_tx =
+ ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
+ num_of_time_rx =
+ ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
+
+ }
+ return Status;
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Procedure: ValidateDSDParamsChecksum
+ *
+ * Description: Reads DSD Params and validates checkusm.
+ *
+ * Arguments:
+ * Adapter - Pointer to Adapter structure.
+ * ulParamOffset - Start offset of the DSD parameter to be read and
+ * validated.
+ * usParamLen - Length of the DSD Parameter.
+ *
+ * Returns:
+ * <OSAL_STATUS_CODE>
+ * -----------------------------------------------------------------------------
+ */
+static INT ValidateDSDParamsChecksum(struct bcm_mini_adapter *Adapter, ULONG ulParamOffset,
+ USHORT usParamLen)
+{
+ INT Status = STATUS_SUCCESS;
+ PUCHAR puBuffer = NULL;
+ USHORT usChksmOrg = 0;
+ USHORT usChecksumCalculated = 0;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",
+ ulParamOffset, usParamLen);
+
+ puBuffer = kmalloc(usParamLen, GFP_KERNEL);
+ if (!puBuffer) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum Allocation failed");
+ return -ENOMEM;
+
+ }
+
+ /* Read the DSD data from the parameter offset. */
+ if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)puBuffer,
+ ulParamOffset, usParamLen)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
+ goto exit;
+ }
+
+ /* Calculate the checksum of the data read from the DSD parameter. */
+ usChecksumCalculated = CFG_CalculateChecksum(puBuffer, usParamLen);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: usCheckSumCalculated = 0x%x\n",
+ usChecksumCalculated);
+
+ /*
+ * End of the DSD parameter will have a TWO bytes checksum stored in it.
+ * Read it and compare with the calculated Checksum.
+ */
+ if (STATUS_SUCCESS != BeceemNVMRead(Adapter, (PUINT)&usChksmOrg,
+ ulParamOffset+usParamLen, 2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
+ goto exit;
+ }
+ usChksmOrg = ntohs(usChksmOrg);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: usChksmOrg = 0x%x", usChksmOrg);
+
+ /*
+ * Compare the checksum calculated with the checksum read
+ * from DSD section
+ */
+ if (usChecksumCalculated ^ usChksmOrg) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
+ goto exit;
+ }
+
+exit:
+ kfree(puBuffer);
+ return Status;
+}
+
+
+/*
+ * -----------------------------------------------------------------------------
+ * Procedure: ValidateHWParmStructure
+ *
+ * Description: Validates HW Parameters.
+ *
+ * Arguments:
+ * Adapter - Pointer to Adapter structure.
+ * ulHwParamOffset - Start offset of the HW parameter Section to be read
+ * and validated.
+ *
+ * Returns:
+ * <OSAL_STATUS_CODE>
+ * -----------------------------------------------------------------------------
+ */
+static INT ValidateHWParmStructure(struct bcm_mini_adapter *Adapter, ULONG ulHwParamOffset)
+{
+
+ INT Status = STATUS_SUCCESS;
+ USHORT HwParamLen = 0;
+ /*
+ * Add DSD start offset to the hwParamOffset to get
+ * the actual address.
+ */
+ ulHwParamOffset += DSD_START_OFFSET;
+
+ /* Read the Length of HW_PARAM structure */
+ BeceemNVMRead(Adapter, (PUINT)&HwParamLen, ulHwParamOffset, 2);
+ HwParamLen = ntohs(HwParamLen);
+ if (0 == HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
+ return STATUS_IMAGE_CHECKSUM_MISMATCH;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread:HwParamLen = 0x%x", HwParamLen);
+ Status = ValidateDSDParamsChecksum(Adapter, ulHwParamOffset,
+ HwParamLen);
+ return Status;
+} /* ValidateHWParmStructure() */
+
+static int ReadLEDInformationFromEEPROM(struct bcm_mini_adapter *Adapter,
+ UCHAR GPIO_Array[])
+{
+ int Status = STATUS_SUCCESS;
+
+ ULONG dwReadValue = 0;
+ USHORT usHwParamData = 0;
+ USHORT usEEPROMVersion = 0;
+ UCHAR ucIndex = 0;
+ UCHAR ucGPIOInfo[32] = {0};
+
+ BeceemNVMRead(Adapter, (PUINT)&usEEPROMVersion,
+ EEPROM_VERSION_OFFSET, 2);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "usEEPROMVersion: Minor:0x%X Major:0x%x",
+ usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
+
+
+ if (((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION) {
+ BeceemNVMRead(Adapter, (PUINT)&usHwParamData,
+ EEPROM_HW_PARAM_POINTER_ADDRESS, 2);
+ usHwParamData = ntohs(usHwParamData);
+ dwReadValue = usHwParamData;
+ } else {
+ /*
+ * Validate Compatibility section and then read HW param
+ * if compatibility section is valid.
+ */
+ Status = ValidateDSDParamsChecksum(Adapter,
+ DSD_START_OFFSET,
+ COMPATIBILITY_SECTION_LENGTH_MAP5);
+
+ if (Status != STATUS_SUCCESS)
+ return Status;
+
+ BeceemNVMRead(Adapter, (PUINT)&dwReadValue,
+ EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5, 4);
+ dwReadValue = ntohl(dwReadValue);
+ }
+
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: Start address of HW_PARAM structure = 0x%lx",
+ dwReadValue);
+
+ /*
+ * Validate if the address read out is within the DSD.
+ * Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
+ * lower limit should be above DSD_START_OFFSET and
+ * upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
+ */
+ if (dwReadValue < DSD_START_OFFSET ||
+ dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
+ return STATUS_IMAGE_CHECKSUM_MISMATCH;
+
+ Status = ValidateHWParmStructure(Adapter, dwReadValue);
+ if (Status)
+ return Status;
+
+ /*
+ * Add DSD_START_OFFSET to the offset read from the EEPROM.
+ * This will give the actual start HW Parameters start address.
+ * To read GPIO section, add GPIO offset further.
+ */
+
+ dwReadValue +=
+ DSD_START_OFFSET; /* = start address of hw param section. */
+ dwReadValue += GPIO_SECTION_START_OFFSET;
+ /* = GPIO start offset within HW Param section. */
+
+ /*
+ * Read the GPIO values for 32 GPIOs from EEPROM and map the function
+ * number to GPIO pin number to GPIO_Array
+ */
+ BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo, dwReadValue, 32);
+ for (ucIndex = 0; ucIndex < 32; ucIndex++) {
+
+ switch (ucGPIOInfo[ucIndex]) {
+ case RED_LED:
+ GPIO_Array[RED_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ case BLUE_LED:
+ GPIO_Array[BLUE_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ case YELLOW_LED:
+ GPIO_Array[YELLOW_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ case GREEN_LED:
+ GPIO_Array[GREEN_LED] = ucIndex;
+ Adapter->gpioBitMap |= (1 << ucIndex);
+ break;
+ default:
+ break;
+ }
+
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "GPIO's bit map correspond to LED :0x%X", Adapter->gpioBitMap);
+ return Status;
+}
+
+
+static int ReadConfigFileStructure(struct bcm_mini_adapter *Adapter,
+ bool *bEnableThread)
+{
+ int Status = STATUS_SUCCESS;
+ /* Array to store GPIO numbers from EEPROM */
+ UCHAR GPIO_Array[NUM_OF_LEDS+1];
+ UINT uiIndex = 0;
+ UINT uiNum_of_LED_Type = 0;
+ PUCHAR puCFGData = NULL;
+ UCHAR bData = 0;
+ memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
+
+ if (!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "Target Params not Avail.\n");
+ return -ENOENT;
+ }
+
+ /* Populate GPIO_Array with GPIO numbers for LED functions */
+ /* Read the GPIO numbers from EEPROM */
+ Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
+ if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH) {
+ *bEnableThread = false;
+ return STATUS_SUCCESS;
+ } else if (Status) {
+ *bEnableThread = false;
+ return Status;
+ }
+
+ /*
+ * CONFIG file read successfully. Deallocate the memory of
+ * uiFileNameBufferSize
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,
+ "LED Thread: Config file read successfully\n");
+ puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
+
+ /*
+ * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
+ * will have the information of LED type, LED on state for different
+ * driver state and LED blink state.
+ */
+
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ bData = *puCFGData;
+
+ /*
+ * Check Bit 8 for polarity. If it is set,
+ * polarity is reverse polarity
+ */
+ if (bData & 0x80) {
+ Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
+ /* unset the bit 8 */
+ bData = bData & 0x7f;
+ }
+
+ Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
+ if (bData <= NUM_OF_LEDS)
+ Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
+ GPIO_Array[bData];
+ else
+ Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num =
+ DISABLE_GPIO_NUM;
+
+ puCFGData++;
+ bData = *puCFGData;
+ Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
+ puCFGData++;
+ bData = *puCFGData;
+ Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State = bData;
+ puCFGData++;
+ }
+
+ /*
+ * Check if all the LED settings are disabled. If it is disabled,
+ * dont launch the LED control thread.
+ */
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if ((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
+ (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
+ (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
+ uiNum_of_LED_Type++;
+ }
+ if (uiNum_of_LED_Type >= NUM_OF_LEDS)
+ *bEnableThread = false;
+
+ return Status;
+}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Procedure: LedGpioInit
+ *
+ * Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode
+ * and make the initial state to be OFF.
+ *
+ * Arguments:
+ * Adapter - Pointer to MINI_ADAPTER structure.
+ *
+ * Returns: VOID
+ *
+ * -----------------------------------------------------------------------------
+ */
+static VOID LedGpioInit(struct bcm_mini_adapter *Adapter)
+{
+ UINT uiResetValue = 0;
+ UINT uiIndex = 0;
+
+ /* Set all LED GPIO Mode to output mode */
+ if (rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
+ sizeof(uiResetValue)) < 0)
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "LED Thread: RDM Failed\n");
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
+ DISABLE_GPIO_NUM)
+ uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
+ TURN_OFF_LED(1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,
+ uiIndex);
+ }
+ if (wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue,
+ sizeof(uiResetValue)) < 0)
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "LED Thread: WRM Failed\n");
+
+ Adapter->LEDInfo.bIdle_led_off = false;
+}
+
+static INT BcmGetGPIOPinInfo(struct bcm_mini_adapter *Adapter, UCHAR *GPIO_num_tx,
+ UCHAR *GPIO_num_rx, UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,
+ enum bcm_led_events currdriverstate)
+{
+ UINT uiIndex = 0;
+
+ *GPIO_num_tx = DISABLE_GPIO_NUM;
+ *GPIO_num_rx = DISABLE_GPIO_NUM;
+
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+
+ if ((currdriverstate == NORMAL_OPERATION) ||
+ (currdriverstate == IDLEMODE_EXIT) ||
+ (currdriverstate == FW_DOWNLOAD)) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State &
+ currdriverstate) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM) {
+ if (*GPIO_num_tx == DISABLE_GPIO_NUM) {
+ *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
+ *uiLedTxIndex = uiIndex;
+ } else {
+ *GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
+ *uiLedRxIndex = uiIndex;
+ }
+ }
+ }
+ } else {
+ if (Adapter->LEDInfo.LEDState[uiIndex].LED_On_State
+ & currdriverstate) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM) {
+ *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
+ *uiLedTxIndex = uiIndex;
+ }
+ }
+ }
+ }
+ return STATUS_SUCCESS;
+}
+static VOID LEDControlThread(struct bcm_mini_adapter *Adapter)
+{
+ UINT uiIndex = 0;
+ UCHAR GPIO_num = 0;
+ UCHAR uiLedIndex = 0;
+ UINT uiResetValue = 0;
+ enum bcm_led_events currdriverstate = 0;
+ ulong timeout = 0;
+
+ INT Status = 0;
+
+ UCHAR dummyGPIONum = 0;
+ UCHAR dummyIndex = 0;
+
+ /* currdriverstate = Adapter->DriverState; */
+ Adapter->LEDInfo.bIdleMode_tx_from_host = false;
+
+ /*
+ * Wait till event is triggered
+ *
+ * wait_event(Adapter->LEDInfo.notify_led_event,
+ * currdriverstate!= Adapter->DriverState);
+ */
+
+ GPIO_num = DISABLE_GPIO_NUM;
+
+ while (TRUE) {
+ /* Wait till event is triggered */
+ if ((GPIO_num == DISABLE_GPIO_NUM)
+ ||
+ ((currdriverstate != FW_DOWNLOAD) &&
+ (currdriverstate != NORMAL_OPERATION) &&
+ (currdriverstate != LOWPOWER_MODE_ENTER))
+ ||
+ (currdriverstate == LED_THREAD_INACTIVE))
+ Status = wait_event_interruptible(
+ Adapter->LEDInfo.notify_led_event,
+ currdriverstate != Adapter->DriverState
+ || kthread_should_stop());
+
+ if (kthread_should_stop() || Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "Led thread got signal to exit..hence exiting");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
+ return; /* STATUS_FAILURE; */
+ }
+
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
+
+ if (Adapter->LEDInfo.bLedInitDone == false) {
+ LedGpioInit(Adapter);
+ Adapter->LEDInfo.bLedInitDone = TRUE;
+ }
+
+ switch (Adapter->DriverState) {
+ case DRIVER_INIT:
+ currdriverstate = DRIVER_INIT;
+ /* Adapter->DriverState; */
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyIndex, currdriverstate);
+
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_ON_LED(1 << GPIO_num, uiLedIndex);
+
+ break;
+ case FW_DOWNLOAD:
+ /*
+ * BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
+ * LED_DUMP_INFO, DBG_LVL_ALL,
+ * "LED Thread: FW_DN_DONE called\n");
+ */
+ currdriverstate = FW_DOWNLOAD;
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyIndex, currdriverstate);
+
+ if (GPIO_num != DISABLE_GPIO_NUM) {
+ timeout = 50;
+ LED_Blink(Adapter, 1 << GPIO_num, uiLedIndex,
+ timeout, -1, currdriverstate);
+ }
+ break;
+ case FW_DOWNLOAD_DONE:
+ currdriverstate = FW_DOWNLOAD_DONE;
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyIndex, currdriverstate);
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_ON_LED(1 << GPIO_num, uiLedIndex);
+ break;
+
+ case SHUTDOWN_EXIT:
+ /*
+ * no break, continue to NO_NETWORK_ENTRY
+ * state as well.
+ */
+ case NO_NETWORK_ENTRY:
+ currdriverstate = NO_NETWORK_ENTRY;
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,
+ &uiLedIndex, &dummyGPIONum, currdriverstate);
+ if (GPIO_num != DISABLE_GPIO_NUM)
+ TURN_ON_LED(1 << GPIO_num, uiLedIndex);
+ break;
+ case NORMAL_OPERATION:
+ {
+ UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
+ UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
+ UCHAR uiLEDTx = 0;
+ UCHAR uiLEDRx = 0;
+ currdriverstate = NORMAL_OPERATION;
+ Adapter->LEDInfo.bIdle_led_off = false;
+
+ BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx,
+ &GPIO_num_rx, &uiLEDTx, &uiLEDRx,
+ currdriverstate);
+ if ((GPIO_num_tx == DISABLE_GPIO_NUM) &&
+ (GPIO_num_rx ==
+ DISABLE_GPIO_NUM)) {
+ GPIO_num = DISABLE_GPIO_NUM;
+ } else {
+ /*
+ * If single LED is selected, use same
+ * for both Tx and Rx
+ */
+ if (GPIO_num_tx == DISABLE_GPIO_NUM) {
+ GPIO_num_tx = GPIO_num_rx;
+ uiLEDTx = uiLEDRx;
+ } else if (GPIO_num_rx ==
+ DISABLE_GPIO_NUM) {
+ GPIO_num_rx = GPIO_num_tx;
+ uiLEDRx = uiLEDTx;
+ }
+ /*
+ * Blink the LED in proportionate
+ * to Tx and Rx transmissions.
+ */
+ LED_Proportional_Blink(Adapter,
+ GPIO_num_tx, uiLEDTx,
+ GPIO_num_rx, uiLEDRx,
+ currdriverstate);
+ }
+ }
+ break;
+ case LOWPOWER_MODE_ENTER:
+ currdriverstate = LOWPOWER_MODE_ENTER;
+ if (DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING ==
+ Adapter->ulPowerSaveMode) {
+ /* Turn OFF all the LED */
+ uiResetValue = 0;
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
+ TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
+ }
+
+ }
+ /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
+ Adapter->LEDInfo.bLedInitDone = false;
+ Adapter->LEDInfo.bIdle_led_off = TRUE;
+ wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
+ GPIO_num = DISABLE_GPIO_NUM;
+ break;
+ case IDLEMODE_CONTINUE:
+ currdriverstate = IDLEMODE_CONTINUE;
+ GPIO_num = DISABLE_GPIO_NUM;
+ break;
+ case IDLEMODE_EXIT:
+ break;
+ case DRIVER_HALT:
+ currdriverstate = DRIVER_HALT;
+ GPIO_num = DISABLE_GPIO_NUM;
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM)
+ TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
+ }
+ /* Adapter->DriverState = DRIVER_INIT; */
+ break;
+ case LED_THREAD_INACTIVE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "InActivating LED thread...");
+ currdriverstate = LED_THREAD_INACTIVE;
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_RUNNING_INACTIVELY;
+ Adapter->LEDInfo.bLedInitDone = false;
+ /* disable ALL LED */
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
+ if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
+ != DISABLE_GPIO_NUM)
+ TURN_OFF_LED((1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num), uiIndex);
+ }
+ break;
+ case LED_THREAD_ACTIVE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL, "Activating LED thread again...");
+ if (Adapter->LinkUpStatus == false)
+ Adapter->DriverState = NO_NETWORK_ENTRY;
+ else
+ Adapter->DriverState = NORMAL_OPERATION;
+
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_RUNNING_ACTIVELY;
+ break;
+ /* return; */
+ default:
+ break;
+ }
+ }
+ Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
+}
+
+int InitLedSettings(struct bcm_mini_adapter *Adapter)
+{
+ int Status = STATUS_SUCCESS;
+ bool bEnableThread = TRUE;
+ UCHAR uiIndex = 0;
+
+ /*
+ * Initially set BitPolarity to normal polarity. The bit 8 of LED type
+ * is used to change the polarity of the LED.
+ */
+
+ for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
+ Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
+
+ /*
+ * Read the LED settings of CONFIG file and map it
+ * to GPIO numbers in EEPROM
+ */
+ Status = ReadConfigFileStructure(Adapter, &bEnableThread);
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "LED Thread: FAILED in ReadConfigFileStructure\n");
+ return Status;
+ }
+
+ if (Adapter->LEDInfo.led_thread_running) {
+ if (bEnableThread) {
+ ;
+ } else {
+ Adapter->DriverState = DRIVER_HALT;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ }
+
+ } else if (bEnableThread) {
+ /* Create secondary thread to handle the LEDs */
+ init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
+ init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_RUNNING_ACTIVELY;
+ Adapter->LEDInfo.bIdle_led_off = false;
+ Adapter->LEDInfo.led_cntrl_threadid =
+ kthread_run((int (*)(void *)) LEDControlThread,
+ Adapter, "led_control_thread");
+ if (IS_ERR(Adapter->LEDInfo.led_cntrl_threadid)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
+ DBG_LVL_ALL,
+ "Not able to spawn Kernel Thread\n");
+ Adapter->LEDInfo.led_thread_running =
+ BCM_LED_THREAD_DISABLED;
+ return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
+ }
+ }
+ return Status;
+}
diff --git a/drivers/staging/bcm/led_control.h b/drivers/staging/bcm/led_control.h
new file mode 100644
index 00000000000..bae40e22e11
--- /dev/null
+++ b/drivers/staging/bcm/led_control.h
@@ -0,0 +1,84 @@
+#ifndef _LED_CONTROL_H
+#define _LED_CONTROL_H
+
+#define NUM_OF_LEDS 4
+#define DSD_START_OFFSET 0x0200
+#define EEPROM_VERSION_OFFSET 0x020E
+#define EEPROM_HW_PARAM_POINTER_ADDRESS 0x0218
+#define EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5 0x0220
+#define GPIO_SECTION_START_OFFSET 0x03
+#define COMPATIBILITY_SECTION_LENGTH 42
+#define COMPATIBILITY_SECTION_LENGTH_MAP5 84
+#define EEPROM_MAP5_MAJORVERSION 5
+#define EEPROM_MAP5_MINORVERSION 0
+#define MAX_NUM_OF_BLINKS 10
+#define NUM_OF_GPIO_PINS 16
+#define DISABLE_GPIO_NUM 0xFF
+#define EVENT_SIGNALED 1
+#define MAX_FILE_NAME_BUFFER_SIZE 100
+
+#define TURN_ON_LED(GPIO, index) do { \
+ unsigned int gpio_val = GPIO; \
+ (Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ? \
+ wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)) : \
+ wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)); \
+ } while (0)
+
+#define TURN_OFF_LED(GPIO, index) do { \
+ unsigned int gpio_val = GPIO; \
+ (Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ? \
+ wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)) : \
+ wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)); \
+ } while (0)
+
+enum bcm_led_colors {
+ RED_LED = 1,
+ BLUE_LED = 2,
+ YELLOW_LED = 3,
+ GREEN_LED = 4
+};
+
+enum bcm_led_events {
+ SHUTDOWN_EXIT = 0x00,
+ DRIVER_INIT = 0x1,
+ FW_DOWNLOAD = 0x2,
+ FW_DOWNLOAD_DONE = 0x4,
+ NO_NETWORK_ENTRY = 0x8,
+ NORMAL_OPERATION = 0x10,
+ LOWPOWER_MODE_ENTER = 0x20,
+ IDLEMODE_CONTINUE = 0x40,
+ IDLEMODE_EXIT = 0x80,
+ LED_THREAD_INACTIVE = 0x100, /* Makes the LED thread Inactivce. It wil be equivallent to putting the thread on hold. */
+ LED_THREAD_ACTIVE = 0x200, /* Makes the LED Thread Active back. */
+ DRIVER_HALT = 0xff
+}; /* Enumerated values of different driver states */
+
+/*
+ * Structure which stores the information of different LED types
+ * and corresponding LED state information of driver states
+ */
+struct bcm_led_state_info {
+ unsigned char LED_Type; /* specify GPIO number - use 0xFF if not used */
+ unsigned char LED_On_State; /* Bits set or reset for different states */
+ unsigned char LED_Blink_State; /* Bits set or reset for blinking LEDs for different states */
+ unsigned char GPIO_Num;
+ unsigned char BitPolarity; /* To represent whether H/W is normal polarity or reverse polarity */
+};
+
+struct bcm_led_info {
+ struct bcm_led_state_info LEDState[NUM_OF_LEDS];
+ bool bIdleMode_tx_from_host; /* Variable to notify whether driver came out from idlemode due to Host or target */
+ bool bIdle_led_off;
+ wait_queue_head_t notify_led_event;
+ wait_queue_head_t idleModeSyncEvent;
+ struct task_struct *led_cntrl_threadid;
+ int led_thread_running;
+ bool bLedInitDone;
+};
+
+/* LED Thread state. */
+#define BCM_LED_THREAD_DISABLED 0 /* LED Thread is not running. */
+#define BCM_LED_THREAD_RUNNING_ACTIVELY 1 /* LED thread is running. */
+#define BCM_LED_THREAD_RUNNING_INACTIVELY 2 /* LED thread has been put on hold */
+
+#endif
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
new file mode 100644
index 00000000000..63be3be62eb
--- /dev/null
+++ b/drivers/staging/bcm/nvm.c
@@ -0,0 +1,4613 @@
+#include "headers.h"
+
+#define DWORD unsigned int
+
+static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset);
+static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter);
+static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter);
+static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter);
+static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter);
+static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize);
+
+static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter);
+static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter);
+static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter);
+static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter);
+
+static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+
+static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset);
+static int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section);
+static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
+
+static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
+static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
+static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
+static int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
+
+static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiSectAlignAddr);
+static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff,
+ enum bcm_flash2x_section_val eFlash2xSectionVal,
+ unsigned int uiOffset, unsigned int uiNumBytes);
+static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter);
+static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter);
+
+static int BeceemFlashBulkRead(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes);
+
+static int BeceemFlashBulkWrite(
+ struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes,
+ bool bVerify);
+
+static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter);
+
+static int ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, unsigned int dwAddress, unsigned int *pdwData, unsigned int dwNumData);
+
+/* Procedure: ReadEEPROMStatusRegister
+ *
+ * Description: Reads the standard EEPROM Status Register.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * Returns:
+ * OSAL_STATUS_CODE
+ */
+static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter)
+{
+ UCHAR uiData = 0;
+ DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
+ unsigned int uiStatus = 0;
+ unsigned int value = 0;
+ unsigned int value1 = 0;
+
+ /* Read the EEPROM status register */
+ value = EEPROM_READ_STATUS_REGISTER;
+ wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));
+
+ while (dwRetries != 0) {
+ value = 0;
+ uiStatus = 0;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
+ if (Adapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting....");
+ break;
+ }
+
+ /* Wait for Avail bit to be set. */
+ if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) {
+ /* Clear the Avail/Full bits - which ever is set. */
+ value = uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL);
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+
+ value = 0;
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
+ uiData = (UCHAR)value;
+
+ break;
+ }
+
+ dwRetries--;
+ if (dwRetries == 0) {
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x3004 = %x 0x3008 = %x, retries = %d failed.\n", value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
+ return uiData;
+ }
+ if (!(dwRetries%RETRIES_PER_DELAY))
+ udelay(1000);
+ uiStatus = 0;
+ }
+ return uiData;
+} /* ReadEEPROMStatusRegister */
+
+/*
+ * Procedure: ReadBeceemEEPROMBulk
+ *
+ * Description: This routine reads 16Byte data from EEPROM
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * dwAddress - EEPROM Offset to read the data from.
+ * pdwData - Pointer to double word where data needs to be stored in. // dwNumWords - Number of words. Valid values are 4 ONLY.
+ *
+ * Returns:
+ * OSAL_STATUS_CODE:
+ */
+
+static int ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter,
+ DWORD dwAddress,
+ DWORD *pdwData,
+ DWORD dwNumWords)
+{
+ DWORD dwIndex = 0;
+ DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
+ unsigned int uiStatus = 0;
+ unsigned int value = 0;
+ unsigned int value1 = 0;
+ UCHAR *pvalue;
+
+ /* Flush the read and cmd queue. */
+ value = (EEPROM_READ_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH);
+ wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
+ value = 0;
+ wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
+
+ /* Clear the Avail/Full bits. */
+ value = (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL);
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+
+ value = dwAddress | ((dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ);
+ wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));
+
+ while (dwRetries != 0) {
+ uiStatus = 0;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
+ if (Adapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got Removed.hence exiting from loop...");
+ return -ENODEV;
+ }
+
+ /* If we are reading 16 bytes we want to be sure that the queue
+ * is full before we read. In the other cases we are ok if the
+ * queue has data available
+ */
+ if (dwNumWords == 4) {
+ if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) {
+ /* Clear the Avail/Full bits - which ever is set. */
+ value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL));
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ break;
+ }
+ } else if (dwNumWords == 1) {
+ if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) {
+ /* We just got Avail and we have to read 32bits so we
+ * need this sleep for Cardbus kind of devices.
+ */
+ if (Adapter->chip_id == 0xBECE0210)
+ udelay(800);
+
+ /* Clear the Avail/Full bits - which ever is set. */
+ value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL));
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ break;
+ }
+ }
+
+ uiStatus = 0;
+
+ dwRetries--;
+ if (dwRetries == 0) {
+ value = 0;
+ value1 = 0;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n",
+ dwNumWords, value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
+ return STATUS_FAILURE;
+ }
+
+ if (!(dwRetries%RETRIES_PER_DELAY))
+ udelay(1000);
+ }
+
+ for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) {
+ /* We get only a byte at a time - from LSB to MSB. We shift it into an integer. */
+ pvalue = (PUCHAR)(pdwData + dwIndex);
+
+ value = 0;
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
+
+ pvalue[0] = value;
+
+ value = 0;
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
+
+ pvalue[1] = value;
+
+ value = 0;
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
+
+ pvalue[2] = value;
+
+ value = 0;
+ rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
+
+ pvalue[3] = value;
+ }
+
+ return STATUS_SUCCESS;
+} /* ReadBeceemEEPROMBulk() */
+
+/*
+ * Procedure: ReadBeceemEEPROM
+ *
+ * Description: This routine reads 4 data from EEPROM. It uses 1 or 2 page
+ * reads to do this operation.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiOffset - EEPROM Offset to read the data from.
+ * pBuffer - Pointer to word where data needs to be stored in.
+ *
+ * Returns:
+ * OSAL_STATUS_CODE:
+ */
+
+int ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter,
+ DWORD uiOffset,
+ DWORD *pBuffer)
+{
+ unsigned int uiData[8] = {0};
+ unsigned int uiByteOffset = 0;
+ unsigned int uiTempOffset = 0;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ====> ");
+
+ uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
+ uiByteOffset = uiOffset - uiTempOffset;
+
+ ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4);
+
+ /* A word can overlap at most over 2 pages. In that case we read the
+ * next page too.
+ */
+ if (uiByteOffset > 12)
+ ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4);
+
+ memcpy((PUCHAR)pBuffer, (((PUCHAR)&uiData[0]) + uiByteOffset), 4);
+
+ return STATUS_SUCCESS;
+} /* ReadBeceemEEPROM() */
+
+int ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter)
+{
+ int Status;
+ unsigned char puMacAddr[6];
+
+ Status = BeceemNVMRead(Adapter,
+ (PUINT)&puMacAddr[0],
+ INIT_PARAMS_1_MACADDRESS_ADDRESS,
+ MAC_ADDRESS_SIZE);
+
+ if (Status == STATUS_SUCCESS)
+ memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE);
+
+ return Status;
+}
+
+/*
+ * Procedure: BeceemEEPROMBulkRead
+ *
+ * Description: Reads the EEPROM and returns the Data.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Buffer to store the data read from EEPROM
+ * uiOffset - Offset of EEPROM from where data should be read
+ * uiNumBytes - Number of bytes to be read from the EEPROM.
+ *
+ * Returns:
+ * OSAL_STATUS_SUCCESS - if EEPROM read is successful.
+ * <FAILURE> - if failed.
+ */
+
+int BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes)
+{
+ unsigned int uiData[4] = {0};
+ /* unsigned int uiAddress = 0; */
+ unsigned int uiBytesRemaining = uiNumBytes;
+ unsigned int uiIndex = 0;
+ unsigned int uiTempOffset = 0;
+ unsigned int uiExtraBytes = 0;
+ unsigned int uiFailureRetries = 0;
+ PUCHAR pcBuff = (PUCHAR)pBuffer;
+
+ if (uiOffset % MAX_RW_SIZE && uiBytesRemaining) {
+ uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
+ uiExtraBytes = uiOffset - uiTempOffset;
+ ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4);
+ if (uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) {
+ memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), MAX_RW_SIZE - uiExtraBytes);
+ uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes);
+ uiIndex += (MAX_RW_SIZE - uiExtraBytes);
+ uiOffset += (MAX_RW_SIZE - uiExtraBytes);
+ } else {
+ memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), uiBytesRemaining);
+ uiIndex += uiBytesRemaining;
+ uiOffset += uiBytesRemaining;
+ uiBytesRemaining = 0;
+ }
+ }
+
+ while (uiBytesRemaining && uiFailureRetries != 128) {
+ if (Adapter->device_removed)
+ return -1;
+
+ if (uiBytesRemaining >= MAX_RW_SIZE) {
+ /* For the requests more than or equal to 16 bytes, use bulk
+ * read function to make the access faster.
+ * We read 4 Dwords of data
+ */
+ if (ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4) == 0) {
+ memcpy(pcBuff + uiIndex, &uiData[0], MAX_RW_SIZE);
+ uiOffset += MAX_RW_SIZE;
+ uiBytesRemaining -= MAX_RW_SIZE;
+ uiIndex += MAX_RW_SIZE;
+ } else {
+ uiFailureRetries++;
+ mdelay(3); /* sleep for a while before retry... */
+ }
+ } else if (uiBytesRemaining >= 4) {
+ if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) {
+ memcpy(pcBuff + uiIndex, &uiData[0], 4);
+ uiOffset += 4;
+ uiBytesRemaining -= 4;
+ uiIndex += 4;
+ } else {
+ uiFailureRetries++;
+ mdelay(3); /* sleep for a while before retry... */
+ }
+ } else {
+ /* Handle the reads less than 4 bytes... */
+ PUCHAR pCharBuff = (PUCHAR)pBuffer;
+ pCharBuff += uiIndex;
+ if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) {
+ memcpy(pCharBuff, &uiData[0], uiBytesRemaining); /* copy only bytes requested. */
+ uiBytesRemaining = 0;
+ } else {
+ uiFailureRetries++;
+ mdelay(3); /* sleep for a while before retry... */
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Procedure: BeceemFlashBulkRead
+ *
+ * Description: Reads the FLASH and returns the Data.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Buffer to store the data read from FLASH
+ * uiOffset - Offset of FLASH from where data should be read
+ * uiNumBytes - Number of bytes to be read from the FLASH.
+ *
+ * Returns:
+ * OSAL_STATUS_SUCCESS - if FLASH read is successful.
+ * <FAILURE> - if failed.
+ */
+
+static int BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes)
+{
+ unsigned int uiIndex = 0;
+ unsigned int uiBytesToRead = uiNumBytes;
+ int Status = 0;
+ unsigned int uiPartOffset = 0;
+ int bytes;
+
+ if (Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device Got Removed");
+ return -ENODEV;
+ }
+
+ /* Adding flash Base address
+ * uiOffset = uiOffset + GetFlashBaseAddr(Adapter);
+ */
+ #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
+ Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
+ return Status;
+ #endif
+
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+
+ if (uiOffset % MAX_RW_SIZE) {
+ BcmDoChipSelect(Adapter, uiOffset);
+ uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
+
+ uiBytesToRead = MAX_RW_SIZE - (uiOffset % MAX_RW_SIZE);
+ uiBytesToRead = MIN(uiNumBytes, uiBytesToRead);
+
+ bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead);
+ if (bytes < 0) {
+ Status = bytes;
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ return Status;
+ }
+
+ uiIndex += uiBytesToRead;
+ uiOffset += uiBytesToRead;
+ uiNumBytes -= uiBytesToRead;
+ }
+
+ while (uiNumBytes) {
+ BcmDoChipSelect(Adapter, uiOffset);
+ uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
+
+ uiBytesToRead = MIN(uiNumBytes, MAX_RW_SIZE);
+
+ bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead);
+ if (bytes < 0) {
+ Status = bytes;
+ break;
+ }
+
+ uiIndex += uiBytesToRead;
+ uiOffset += uiBytesToRead;
+ uiNumBytes -= uiBytesToRead;
+ }
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ return Status;
+}
+
+/*
+ * Procedure: BcmGetFlashSize
+ *
+ * Description: Finds the size of FLASH.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * unsigned int - size of the FLASH Storage.
+ *
+ */
+
+static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter)
+{
+ if (IsFlash2x(Adapter))
+ return Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header);
+ else
+ return 32 * 1024;
+}
+
+/*
+ * Procedure: BcmGetEEPROMSize
+ *
+ * Description: Finds the size of EEPROM.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * unsigned int - size of the EEPROM Storage.
+ *
+ */
+
+static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiData = 0;
+ unsigned int uiIndex = 0;
+
+ /*
+ * if EEPROM is present and already Calibrated,it will have
+ * 'BECM' string at 0th offset.
+ * To find the EEPROM size read the possible boundaries of the
+ * EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will
+ * result in wrap around. So when we get the End of the EEPROM we will
+ * get 'BECM' string which is indeed at offset 0.
+ */
+ BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4);
+ if (uiData == BECM) {
+ for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) {
+ BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4);
+ if (uiData == BECM)
+ return uiIndex * 1024;
+ }
+ } else {
+ /*
+ * EEPROM may not be present or not programmed
+ */
+ uiData = 0xBABEFACE;
+ if (BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE) == 0) {
+ uiData = 0;
+ for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) {
+ BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4);
+ if (uiData == 0xBABEFACE)
+ return uiIndex * 1024;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Procedure: FlashSectorErase
+ *
+ * Description: Finds the sector size of the FLASH.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * addr - sector start address
+ * numOfSectors - number of sectors to be erased.
+ *
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int FlashSectorErase(struct bcm_mini_adapter *Adapter,
+ unsigned int addr,
+ unsigned int numOfSectors)
+{
+ unsigned int iIndex = 0, iRetries = 0;
+ unsigned int uiStatus = 0;
+ unsigned int value;
+ int bytes;
+
+ for (iIndex = 0; iIndex < numOfSectors; iIndex++) {
+ value = 0x06000000;
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+
+ value = (0xd8000000 | (addr & 0xFFFFFF));
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+ iRetries = 0;
+
+ do {
+ value = (FLASH_CMD_STATUS_REG_READ << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
+ }
+ iRetries++;
+ /* After every try lets make the CPU free for 10 ms. generally time taken by the
+ * the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms
+ * won't hamper performance in any case.
+ */
+ mdelay(10);
+ } while ((uiStatus & 0x1) && (iRetries < 400));
+
+ if (uiStatus & 0x1) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "iRetries crossing the limit of 80000\n");
+ return STATUS_FAILURE;
+ }
+
+ addr += Adapter->uiSectorSize;
+ }
+ return 0;
+}
+/*
+ * Procedure: flashByteWrite
+ *
+ * Description: Performs Byte by Byte write to flash
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * pData - Address of Data to be written.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int flashByteWrite(struct bcm_mini_adapter *Adapter,
+ unsigned int uiOffset,
+ PVOID pData)
+{
+ unsigned int uiStatus = 0;
+ int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
+ unsigned int value;
+ ULONG ulData = *(PUCHAR)pData;
+ int bytes;
+ /*
+ * need not write 0xFF because write requires an erase and erase will
+ * make whole sector 0xFF.
+ */
+
+ if (0xFF == ulData)
+ return STATUS_SUCCESS;
+
+ /* DumpDebug(NVM_RW,("flashWrite ====>\n")); */
+ value = (FLASH_CMD_WRITE_ENABLE << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails");
+ return STATUS_FAILURE;
+ }
+
+ if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails");
+ return STATUS_FAILURE;
+ }
+ value = (0x02000000 | (uiOffset & 0xFFFFFF));
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+
+ /* __udelay(950); */
+
+ do {
+ value = (FLASH_CMD_STATUS_REG_READ << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+ /* __udelay(1); */
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
+ }
+ iRetries--;
+ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
+ udelay(1000);
+
+ } while ((uiStatus & 0x1) && (iRetries > 0));
+
+ if (uiStatus & 0x1) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
+ return STATUS_FAILURE;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Procedure: flashWrite
+ *
+ * Description: Performs write to flash
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * pData - Address of Data to be written.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int flashWrite(struct bcm_mini_adapter *Adapter,
+ unsigned int uiOffset,
+ PVOID pData)
+{
+ /* unsigned int uiStatus = 0;
+ * int iRetries = 0;
+ * unsigned int uiReadBack = 0;
+ */
+ unsigned int uiStatus = 0;
+ int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
+ unsigned int value;
+ unsigned int uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
+ int bytes;
+ /*
+ * need not write 0xFFFFFFFF because write requires an erase and erase will
+ * make whole sector 0xFFFFFFFF.
+ */
+ if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE))
+ return 0;
+
+ value = (FLASH_CMD_WRITE_ENABLE << 24);
+
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+
+ if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails...");
+ return STATUS_FAILURE;
+ }
+
+ /* __udelay(950); */
+ do {
+ value = (FLASH_CMD_STATUS_REG_READ << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+ /* __udelay(1); */
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
+ }
+
+ iRetries--;
+ /* this will ensure that in there will be no changes in the current path.
+ * currently one rdm/wrm takes 125 us.
+ * Hence 125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay)
+ * Hence current implementation cycle will intoduce no delay in current path
+ */
+ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
+ udelay(1000);
+ } while ((uiStatus & 0x1) && (iRetries > 0));
+
+ if (uiStatus & 0x1) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
+ return STATUS_FAILURE;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+ * Procedure: flashByteWriteStatus
+ *
+ * Description: Performs byte by byte write to flash with write done status check
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * pData - Address of the Data to be written.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+static int flashByteWriteStatus(struct bcm_mini_adapter *Adapter,
+ unsigned int uiOffset,
+ PVOID pData)
+{
+ unsigned int uiStatus = 0;
+ int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
+ ULONG ulData = *(PUCHAR)pData;
+ unsigned int value;
+ int bytes;
+
+ /*
+ * need not write 0xFFFFFFFF because write requires an erase and erase will
+ * make whole sector 0xFFFFFFFF.
+ */
+
+ if (0xFF == ulData)
+ return STATUS_SUCCESS;
+
+ /* DumpDebug(NVM_RW,("flashWrite ====>\n")); */
+
+ value = (FLASH_CMD_WRITE_ENABLE << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails");
+ return STATUS_SUCCESS;
+ }
+ if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails");
+ return STATUS_FAILURE;
+ }
+ value = (0x02000000 | (uiOffset & 0xFFFFFF));
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+
+ /* msleep(1); */
+
+ do {
+ value = (FLASH_CMD_STATUS_REG_READ << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+ /* __udelay(1); */
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
+ }
+
+ iRetries--;
+ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
+ udelay(1000);
+
+ } while ((uiStatus & 0x1) && (iRetries > 0));
+
+ if (uiStatus & 0x1) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
+ return STATUS_FAILURE;
+ }
+
+ return STATUS_SUCCESS;
+}
+/*
+ * Procedure: flashWriteStatus
+ *
+ * Description: Performs write to flash with write done status check
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * pData - Address of the Data to be written.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int flashWriteStatus(struct bcm_mini_adapter *Adapter,
+ unsigned int uiOffset,
+ PVOID pData)
+{
+ unsigned int uiStatus = 0;
+ int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
+ /* unsigned int uiReadBack = 0; */
+ unsigned int value;
+ unsigned int uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
+ int bytes;
+
+ /*
+ * need not write 0xFFFFFFFF because write requires an erase and erase will
+ * make whole sector 0xFFFFFFFF.
+ */
+ if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE))
+ return 0;
+
+ value = (FLASH_CMD_WRITE_ENABLE << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+
+ if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails...");
+ return STATUS_FAILURE;
+ }
+ /* __udelay(1); */
+
+ do {
+ value = (FLASH_CMD_STATUS_REG_READ << 24);
+ if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
+ return STATUS_FAILURE;
+ }
+ /* __udelay(1); */
+ bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
+ if (bytes < 0) {
+ uiStatus = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
+ return uiStatus;
+ }
+ iRetries--;
+ /* this will ensure that in there will be no changes in the current path.
+ * currently one rdm/wrm takes 125 us.
+ * Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay)
+ * Hence current implementation cycle will intoduce no delay in current path
+ */
+ if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
+ udelay(1000);
+
+ } while ((uiStatus & 0x1) && (iRetries > 0));
+
+ if (uiStatus & 0x1) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
+ return STATUS_FAILURE;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Procedure: BcmRestoreBlockProtectStatus
+ *
+ * Description: Restores the original block protection status.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * ulWriteStatus -Original status
+ * Returns:
+ * <VOID>
+ *
+ */
+
+static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG ulWriteStatus)
+{
+ unsigned int value;
+ value = (FLASH_CMD_WRITE_ENABLE << 24);
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+
+ udelay(20);
+ value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16);
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+ udelay(20);
+}
+
+/*
+ * Procedure: BcmFlashUnProtectBlock
+ *
+ * Description: UnProtects appropriate blocks for writing.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiOffset - Offset of the flash where data needs to be written to. This should be Sector aligned.
+ * Returns:
+ * ULONG - Status value before UnProtect.
+ *
+ */
+
+static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, unsigned int uiOffset, unsigned int uiLength)
+{
+ ULONG ulStatus = 0;
+ ULONG ulWriteStatus = 0;
+ unsigned int value;
+
+ uiOffset = uiOffset&0x000FFFFF;
+ /*
+ * Implemented only for 1MB Flash parts.
+ */
+ if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) {
+ /*
+ * Get Current BP status.
+ */
+ value = (FLASH_CMD_STATUS_REG_READ << 24);
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+ udelay(10);
+ /*
+ * Read status will be WWXXYYZZ. We have to take only WW.
+ */
+ rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulStatus, sizeof(ulStatus));
+ ulStatus >>= 24;
+ ulWriteStatus = ulStatus;
+ /*
+ * Bits [5-2] give current block level protection status.
+ * Bit5: BP3 - DONT CARE
+ * BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4
+ * 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS
+ */
+
+ if (ulStatus) {
+ if ((uiOffset+uiLength) <= 0x80000) {
+ /*
+ * Offset comes in lower half of 1MB. Protect the upper half.
+ * Clear BP1 and BP0 and set BP2.
+ */
+ ulWriteStatus |= (0x4<<2);
+ ulWriteStatus &= ~(0x3<<2);
+ } else if ((uiOffset + uiLength) <= 0xC0000) {
+ /*
+ * Offset comes below Upper 1/4. Upper 1/4 can be protected.
+ * Clear BP2 and set BP1 and BP0.
+ */
+ ulWriteStatus |= (0x3<<2);
+ ulWriteStatus &= ~(0x1<<4);
+ } else if ((uiOffset + uiLength) <= 0xE0000) {
+ /*
+ * Offset comes below Upper 1/8. Upper 1/8 can be protected.
+ * Clear BP2 and BP0 and set BP1
+ */
+ ulWriteStatus |= (0x1<<3);
+ ulWriteStatus &= ~(0x5<<2);
+ } else if ((uiOffset + uiLength) <= 0xF0000) {
+ /*
+ * Offset comes below Upper 1/16. Only upper 1/16 can be protected.
+ * Set BP0 and Clear BP2,BP1.
+ */
+ ulWriteStatus |= (0x1<<2);
+ ulWriteStatus &= ~(0x3<<3);
+ } else {
+ /*
+ * Unblock all.
+ * Clear BP2,BP1 and BP0.
+ */
+ ulWriteStatus &= ~(0x7<<2);
+ }
+
+ value = (FLASH_CMD_WRITE_ENABLE << 24);
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+ udelay(20);
+ value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16);
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+ udelay(20);
+ }
+ }
+ return ulStatus;
+}
+
+/*
+ * Procedure: BeceemFlashBulkWrite
+ *
+ * Description: Performs write to the flash
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Data to be written.
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * uiNumBytes - Number of bytes to be written.
+ * bVerify - read verify flag.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes,
+ bool bVerify)
+{
+ PCHAR pTempBuff = NULL;
+ PUCHAR pcBuffer = (PUCHAR)pBuffer;
+ unsigned int uiIndex = 0;
+ unsigned int uiOffsetFromSectStart = 0;
+ unsigned int uiSectAlignAddr = 0;
+ unsigned int uiCurrSectOffsetAddr = 0;
+ unsigned int uiSectBoundary = 0;
+ unsigned int uiNumSectTobeRead = 0;
+ UCHAR ucReadBk[16] = {0};
+ ULONG ulStatus = 0;
+ int Status = STATUS_SUCCESS;
+ unsigned int uiTemp = 0;
+ unsigned int index = 0;
+ unsigned int uiPartOffset = 0;
+
+ #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
+ Status = bcmflash_raw_write((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
+ return Status;
+ #endif
+
+ uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1);
+
+ /* Adding flash Base address
+ * uiOffset = uiOffset + GetFlashBaseAddr(Adapter);
+ */
+
+ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
+ uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1);
+ uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize;
+
+ pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL);
+ if (!pTempBuff)
+ goto BeceemFlashBulkWrite_EXIT;
+ /*
+ * check if the data to be written is overlapped across sectors
+ */
+ if (uiOffset+uiNumBytes < uiSectBoundary) {
+ uiNumSectTobeRead = 1;
+ } else {
+ /* Number of sectors = Last sector start address/First sector start address */
+ uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize;
+ if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize)
+ uiNumSectTobeRead++;
+ }
+ /* Check whether Requested sector is writable or not in case of flash2x write. But if write call is
+ * for DSD calibration, allow it without checking of sector permission
+ */
+
+ if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == false)) {
+ index = 0;
+ uiTemp = uiNumSectTobeRead;
+ while (uiTemp) {
+ if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%X> is not writable",
+ (uiOffsetFromSectStart + index * Adapter->uiSectorSize));
+ Status = SECTOR_IS_NOT_WRITABLE;
+ goto BeceemFlashBulkWrite_EXIT;
+ }
+ uiTemp = uiTemp - 1;
+ index = index + 1;
+ }
+ }
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ while (uiNumSectTobeRead) {
+ /* do_gettimeofday(&tv1);
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000));
+ */
+ uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
+
+ BcmDoChipSelect(Adapter, uiSectAlignAddr);
+
+ if (0 != BeceemFlashBulkRead(Adapter,
+ (PUINT)pTempBuff,
+ uiOffsetFromSectStart,
+ Adapter->uiSectorSize)) {
+ Status = -1;
+ goto BeceemFlashBulkWrite_EXIT;
+ }
+
+ /* do_gettimeofday(&tr);
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000));
+ */
+ ulStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize);
+
+ if (uiNumSectTobeRead > 1) {
+ memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
+ pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)));
+ uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
+ } else {
+ memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes);
+ }
+
+ if (IsFlash2x(Adapter))
+ SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart);
+
+ FlashSectorErase(Adapter, uiPartOffset, 1);
+ /* do_gettimeofday(&te);
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000));
+ */
+ for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) {
+ if (Adapter->device_removed) {
+ Status = -1;
+ goto BeceemFlashBulkWrite_EXIT;
+ }
+
+ if (STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter, uiPartOffset + uiIndex, (&pTempBuff[uiIndex]))) {
+ Status = -1;
+ goto BeceemFlashBulkWrite_EXIT;
+ }
+ }
+
+ /* do_gettimeofday(&tw);
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000));
+ */
+ for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) {
+ if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) {
+ if (Adapter->ulFlashWriteSize == 1) {
+ unsigned int uiReadIndex = 0;
+ for (uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) {
+ if (ucReadBk[uiReadIndex] != pTempBuff[uiIndex + uiReadIndex]) {
+ if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex + uiReadIndex, &pTempBuff[uiIndex+uiReadIndex])) {
+ Status = STATUS_FAILURE;
+ goto BeceemFlashBulkWrite_EXIT;
+ }
+ }
+ }
+ } else {
+ if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) {
+ if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex, &pTempBuff[uiIndex])) {
+ Status = STATUS_FAILURE;
+ goto BeceemFlashBulkWrite_EXIT;
+ }
+ }
+ }
+ }
+ }
+ /* do_gettimeofday(&twv);
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000));
+ */
+ if (ulStatus) {
+ BcmRestoreBlockProtectStatus(Adapter, ulStatus);
+ ulStatus = 0;
+ }
+
+ uiCurrSectOffsetAddr = 0;
+ uiSectAlignAddr = uiSectBoundary;
+ uiSectBoundary += Adapter->uiSectorSize;
+ uiOffsetFromSectStart += Adapter->uiSectorSize;
+ uiNumSectTobeRead--;
+ }
+ /* do_gettimeofday(&tv2);
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000));
+ * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000));
+ *
+ * Cleanup.
+ */
+BeceemFlashBulkWrite_EXIT:
+ if (ulStatus)
+ BcmRestoreBlockProtectStatus(Adapter, ulStatus);
+
+ kfree(pTempBuff);
+
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ return Status;
+}
+
+/*
+ * Procedure: BeceemFlashBulkWriteStatus
+ *
+ * Description: Writes to Flash. Checks the SPI status after each write.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Data to be written.
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * uiNumBytes - Number of bytes to be written.
+ * bVerify - read verify flag.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes,
+ bool bVerify)
+{
+ PCHAR pTempBuff = NULL;
+ PUCHAR pcBuffer = (PUCHAR)pBuffer;
+ unsigned int uiIndex = 0;
+ unsigned int uiOffsetFromSectStart = 0;
+ unsigned int uiSectAlignAddr = 0;
+ unsigned int uiCurrSectOffsetAddr = 0;
+ unsigned int uiSectBoundary = 0;
+ unsigned int uiNumSectTobeRead = 0;
+ UCHAR ucReadBk[16] = {0};
+ ULONG ulStatus = 0;
+ unsigned int Status = STATUS_SUCCESS;
+ unsigned int uiTemp = 0;
+ unsigned int index = 0;
+ unsigned int uiPartOffset = 0;
+
+ uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1);
+
+ /* uiOffset += Adapter->ulFlashCalStart;
+ * Adding flash Base address
+ * uiOffset = uiOffset + GetFlashBaseAddr(Adapter);
+ */
+ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
+ uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1);
+ uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize;
+
+ pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL);
+ if (!pTempBuff)
+ goto BeceemFlashBulkWriteStatus_EXIT;
+
+ /*
+ * check if the data to be written is overlapped across sectors
+ */
+ if (uiOffset+uiNumBytes < uiSectBoundary) {
+ uiNumSectTobeRead = 1;
+ } else {
+ /* Number of sectors = Last sector start address/First sector start address */
+ uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize;
+ if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize)
+ uiNumSectTobeRead++;
+ }
+
+ if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == false)) {
+ index = 0;
+ uiTemp = uiNumSectTobeRead;
+ while (uiTemp) {
+ if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%x> is not writable",
+ (uiOffsetFromSectStart + index * Adapter->uiSectorSize));
+ Status = SECTOR_IS_NOT_WRITABLE;
+ goto BeceemFlashBulkWriteStatus_EXIT;
+ }
+ uiTemp = uiTemp - 1;
+ index = index + 1;
+ }
+ }
+
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ while (uiNumSectTobeRead) {
+ uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
+
+ BcmDoChipSelect(Adapter, uiSectAlignAddr);
+ if (0 != BeceemFlashBulkRead(Adapter,
+ (PUINT)pTempBuff,
+ uiOffsetFromSectStart,
+ Adapter->uiSectorSize)) {
+ Status = -1;
+ goto BeceemFlashBulkWriteStatus_EXIT;
+ }
+
+ ulStatus = BcmFlashUnProtectBlock(Adapter, uiOffsetFromSectStart, Adapter->uiSectorSize);
+
+ if (uiNumSectTobeRead > 1) {
+ memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
+ pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)));
+ uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
+ } else {
+ memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes);
+ }
+
+ if (IsFlash2x(Adapter))
+ SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart);
+
+ FlashSectorErase(Adapter, uiPartOffset, 1);
+
+ for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) {
+ if (Adapter->device_removed) {
+ Status = -1;
+ goto BeceemFlashBulkWriteStatus_EXIT;
+ }
+
+ if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset+uiIndex, &pTempBuff[uiIndex])) {
+ Status = -1;
+ goto BeceemFlashBulkWriteStatus_EXIT;
+ }
+ }
+
+ if (bVerify) {
+ for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) {
+ if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) {
+ if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) {
+ Status = STATUS_FAILURE;
+ goto BeceemFlashBulkWriteStatus_EXIT;
+ }
+ }
+ }
+ }
+
+ if (ulStatus) {
+ BcmRestoreBlockProtectStatus(Adapter, ulStatus);
+ ulStatus = 0;
+ }
+
+ uiCurrSectOffsetAddr = 0;
+ uiSectAlignAddr = uiSectBoundary;
+ uiSectBoundary += Adapter->uiSectorSize;
+ uiOffsetFromSectStart += Adapter->uiSectorSize;
+ uiNumSectTobeRead--;
+ }
+/*
+ * Cleanup.
+ */
+BeceemFlashBulkWriteStatus_EXIT:
+ if (ulStatus)
+ BcmRestoreBlockProtectStatus(Adapter, ulStatus);
+
+ kfree(pTempBuff);
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ return Status;
+}
+
+/*
+ * Procedure: PropagateCalParamsFromFlashToMemory
+ *
+ * Description: Dumps the calibration section of EEPROM to DDR.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+int PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter)
+{
+ PCHAR pBuff, pPtr;
+ unsigned int uiEepromSize = 0;
+ unsigned int uiBytesToCopy = 0;
+ /* unsigned int uiIndex = 0; */
+ unsigned int uiCalStartAddr = EEPROM_CALPARAM_START;
+ unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
+ unsigned int value;
+ int Status = 0;
+
+ /*
+ * Write the signature first. This will ensure firmware does not access EEPROM.
+ */
+ value = 0xbeadbead;
+ wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
+ value = 0xbeadbead;
+ wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
+
+ if (0 != BeceemNVMRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4))
+ return -1;
+
+ uiEepromSize = ntohl(uiEepromSize);
+ uiEepromSize >>= 16;
+
+ /*
+ * subtract the auto init section size
+ */
+ uiEepromSize -= EEPROM_CALPARAM_START;
+
+ if (uiEepromSize > 1024 * 1024)
+ return -1;
+
+ pBuff = kmalloc(uiEepromSize, GFP_KERNEL);
+ if (pBuff == NULL)
+ return -ENOMEM;
+
+ if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) {
+ kfree(pBuff);
+ return -1;
+ }
+
+ pPtr = pBuff;
+
+ uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
+
+ while (uiBytesToCopy) {
+ Status = wrm(Adapter, uiMemoryLoc, (PCHAR)pPtr, uiBytesToCopy);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed with status :%d", Status);
+ break;
+ }
+
+ pPtr += uiBytesToCopy;
+ uiEepromSize -= uiBytesToCopy;
+ uiMemoryLoc += uiBytesToCopy;
+ uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
+ }
+
+ kfree(pBuff);
+ return Status;
+}
+
+/*
+ * Procedure: BeceemEEPROMReadBackandVerify
+ *
+ * Description: Read back the data written and verifies.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Data to be written.
+ * uiOffset - Offset of the flash where data needs to be written to.
+ * uiNumBytes - Number of bytes to be written.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes)
+{
+ unsigned int uiRdbk = 0;
+ unsigned int uiIndex = 0;
+ unsigned int uiData = 0;
+ unsigned int auiData[4] = {0};
+
+ while (uiNumBytes) {
+ if (Adapter->device_removed)
+ return -1;
+
+ if (uiNumBytes >= MAX_RW_SIZE) {
+ /* for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. */
+ BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);
+
+ if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) {
+ /* re-write */
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, false);
+ mdelay(3);
+ BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);
+
+ if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE))
+ return -1;
+ }
+ uiOffset += MAX_RW_SIZE;
+ uiNumBytes -= MAX_RW_SIZE;
+ uiIndex += 4;
+ } else if (uiNumBytes >= 4) {
+ BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
+ if (uiData != pBuffer[uiIndex]) {
+ /* re-write */
+ BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, false);
+ mdelay(3);
+ BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
+ if (uiData != pBuffer[uiIndex])
+ return -1;
+ }
+ uiOffset += 4;
+ uiNumBytes -= 4;
+ uiIndex++;
+ } else {
+ /* Handle the reads less than 4 bytes... */
+ uiData = 0;
+ memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(unsigned int)), uiNumBytes);
+ BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4);
+
+ if (memcmp(&uiData, &uiRdbk, uiNumBytes))
+ return -1;
+
+ uiNumBytes = 0;
+ }
+ }
+
+ return 0;
+}
+
+static VOID BcmSwapWord(unsigned int *ptr1)
+{
+ unsigned int tempval = (unsigned int)*ptr1;
+ char *ptr2 = (char *)&tempval;
+ char *ptr = (char *)ptr1;
+
+ ptr[0] = ptr2[3];
+ ptr[1] = ptr2[2];
+ ptr[2] = ptr2[1];
+ ptr[3] = ptr2[0];
+}
+
+/*
+ * Procedure: BeceemEEPROMWritePage
+ *
+ * Description: Performs page write (16bytes) to the EEPROM
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiData - Data to be written.
+ * uiOffset - Offset of the EEPROM where data needs to be written to.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+static int BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, unsigned int uiData[], unsigned int uiOffset)
+{
+ unsigned int uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
+ unsigned int uiStatus = 0;
+ UCHAR uiEpromStatus = 0;
+ unsigned int value = 0;
+
+ /* Flush the Write/Read/Cmd queues. */
+ value = (EEPROM_WRITE_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH | EEPROM_READ_QUEUE_FLUSH);
+ wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
+ value = 0;
+ wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
+
+ /* Clear the Empty/Avail/Full bits. After this it has been confirmed
+ * that the bit was cleared by reading back the register. See NOTE below.
+ * We also clear the Read queues as we do a EEPROM status register read
+ * later.
+ */
+ value = (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL);
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+
+ /* Enable write */
+ value = EEPROM_WRITE_ENABLE;
+ wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));
+
+ /* We can write back to back 8bits * 16 into the queue and as we have
+ * checked for the queue to be empty we can write in a burst.
+ */
+
+ value = uiData[0];
+ BcmSwapWord(&value);
+ wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
+
+ value = uiData[1];
+ BcmSwapWord(&value);
+ wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
+
+ value = uiData[2];
+ BcmSwapWord(&value);
+ wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
+
+ value = uiData[3];
+ BcmSwapWord(&value);
+ wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
+
+ /* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG
+ * shows that we see 7 for the EEPROM data write. Which means that
+ * queue got full, also space is available as well as the queue is empty.
+ * This may happen in sequence.
+ */
+ value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset;
+ wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));
+
+ /* Ideally we should loop here without tries and eventually succeed.
+ * What we are checking if the previous write has completed, and this
+ * may take time. We should wait till the Empty bit is set.
+ */
+ uiStatus = 0;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
+ while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) {
+ uiRetries--;
+ if (uiRetries == 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
+ return STATUS_FAILURE;
+ }
+
+ if (!(uiRetries%RETRIES_PER_DELAY))
+ udelay(1000);
+
+ uiStatus = 0;
+ rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
+ if (Adapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem got removed hence exiting from loop....");
+ return -ENODEV;
+ }
+ }
+
+ if (uiRetries != 0) {
+ /* Clear the ones that are set - either, Empty/Full/Avail bits */
+ value = (uiStatus & (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL));
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+ }
+
+ /* Here we should check if the EEPROM status register is correct before
+ * proceeding. Bit 0 in the EEPROM Status register should be 0 before
+ * we proceed further. A 1 at Bit 0 indicates that the EEPROM is busy
+ * with the previous write. Note also that issuing this read finally
+ * means the previous write to the EEPROM has completed.
+ */
+ uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
+ uiEpromStatus = 0;
+ while (uiRetries != 0) {
+ uiEpromStatus = ReadEEPROMStatusRegister(Adapter);
+ if (Adapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop...");
+ return -ENODEV;
+ }
+ if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY - uiRetries));
+ return STATUS_SUCCESS;
+ }
+ uiRetries--;
+ if (uiRetries == 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, for EEPROM status read %d retries failed.\n", uiEpromStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
+ return STATUS_FAILURE;
+ }
+ uiEpromStatus = 0;
+ if (!(uiRetries%RETRIES_PER_DELAY))
+ udelay(1000);
+ }
+
+ return STATUS_SUCCESS;
+} /* BeceemEEPROMWritePage */
+
+/*
+ * Procedure: BeceemEEPROMBulkWrite
+ *
+ * Description: Performs write to the EEPROM
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Data to be written.
+ * uiOffset - Offset of the EEPROM where data needs to be written to.
+ * uiNumBytes - Number of bytes to be written.
+ * bVerify - read verify flag.
+ * Returns:
+ * OSAL_STATUS_CODE
+ *
+ */
+
+int BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter,
+ PUCHAR pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes,
+ bool bVerify)
+{
+ unsigned int uiBytesToCopy = uiNumBytes;
+ /* unsigned int uiRdbk = 0; */
+ unsigned int uiData[4] = {0};
+ unsigned int uiIndex = 0;
+ unsigned int uiTempOffset = 0;
+ unsigned int uiExtraBytes = 0;
+ /* PUINT puiBuffer = (PUINT)pBuffer;
+ * int value;
+ */
+
+ if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) {
+ uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
+ uiExtraBytes = uiOffset - uiTempOffset;
+
+ BeceemEEPROMBulkRead(Adapter, &uiData[0], uiTempOffset, MAX_RW_SIZE);
+
+ if (uiBytesToCopy >= (16 - uiExtraBytes)) {
+ memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, MAX_RW_SIZE - uiExtraBytes);
+
+ if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset))
+ return STATUS_FAILURE;
+
+ uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes);
+ uiIndex += (MAX_RW_SIZE - uiExtraBytes);
+ uiOffset += (MAX_RW_SIZE - uiExtraBytes);
+ } else {
+ memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, uiBytesToCopy);
+
+ if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset))
+ return STATUS_FAILURE;
+
+ uiIndex += uiBytesToCopy;
+ uiOffset += uiBytesToCopy;
+ uiBytesToCopy = 0;
+ }
+ }
+
+ while (uiBytesToCopy) {
+ if (Adapter->device_removed)
+ return -1;
+
+ if (uiBytesToCopy >= MAX_RW_SIZE) {
+ if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, (PUINT) &pBuffer[uiIndex], uiOffset))
+ return STATUS_FAILURE;
+
+ uiIndex += MAX_RW_SIZE;
+ uiOffset += MAX_RW_SIZE;
+ uiBytesToCopy -= MAX_RW_SIZE;
+ } else {
+ /*
+ * To program non 16byte aligned data, read 16byte and then update.
+ */
+ BeceemEEPROMBulkRead(Adapter, &uiData[0], uiOffset, 16);
+ memcpy(&uiData[0], pBuffer + uiIndex, uiBytesToCopy);
+
+ if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiOffset))
+ return STATUS_FAILURE;
+
+ uiBytesToCopy = 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Procedure: BeceemNVMRead
+ *
+ * Description: Reads n number of bytes from NVM.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Buffer to store the data read from NVM
+ * uiOffset - Offset of NVM from where data should be read
+ * uiNumBytes - Number of bytes to be read from the NVM.
+ *
+ * Returns:
+ * OSAL_STATUS_SUCCESS - if NVM read is successful.
+ * <FAILURE> - if failed.
+ */
+
+int BeceemNVMRead(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes)
+{
+ int Status = 0;
+
+ #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
+ unsigned int uiTemp = 0, value;
+ #endif
+
+ if (Adapter->eNVMType == NVM_FLASH) {
+ if (Adapter->bFlashRawRead == false) {
+ if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
+ return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes);
+
+ uiOffset = uiOffset + Adapter->ulFlashCalStart;
+ }
+
+ #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
+ Status = bcmflash_raw_read((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
+ #else
+ rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ value = 0;
+ wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
+ Status = BeceemFlashBulkRead(Adapter,
+ pBuffer,
+ uiOffset,
+ uiNumBytes);
+ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ #endif
+ } else if (Adapter->eNVMType == NVM_EEPROM) {
+ Status = BeceemEEPROMBulkRead(Adapter,
+ pBuffer,
+ uiOffset,
+ uiNumBytes);
+ } else {
+ Status = -1;
+ }
+
+ return Status;
+}
+
+/*
+ * Procedure: BeceemNVMWrite
+ *
+ * Description: Writes n number of bytes to NVM.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pBuffer - Buffer contains the data to be written.
+ * uiOffset - Offset of NVM where data to be written to.
+ * uiNumBytes - Number of bytes to be written..
+ *
+ * Returns:
+ * OSAL_STATUS_SUCCESS - if NVM write is successful.
+ * <FAILURE> - if failed.
+ */
+
+int BeceemNVMWrite(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes,
+ bool bVerify)
+{
+ int Status = 0;
+ unsigned int uiTemp = 0;
+ unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
+ unsigned int uiIndex = 0;
+
+ #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
+ unsigned int value;
+ #endif
+
+ unsigned int uiFlashOffset = 0;
+
+ if (Adapter->eNVMType == NVM_FLASH) {
+ if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
+ Status = vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes, bVerify);
+ else {
+ uiFlashOffset = uiOffset + Adapter->ulFlashCalStart;
+
+ #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
+ Status = bcmflash_raw_write((uiFlashOffset / FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
+ #else
+ rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ value = 0;
+ wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
+
+ if (Adapter->bStatusWrite == TRUE)
+ Status = BeceemFlashBulkWriteStatus(Adapter,
+ pBuffer,
+ uiFlashOffset,
+ uiNumBytes ,
+ bVerify);
+ else
+
+ Status = BeceemFlashBulkWrite(Adapter,
+ pBuffer,
+ uiFlashOffset,
+ uiNumBytes,
+ bVerify);
+ #endif
+ }
+
+ if (uiOffset >= EEPROM_CALPARAM_START) {
+ uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START);
+ while (uiNumBytes) {
+ if (uiNumBytes > BUFFER_4K) {
+ wrm(Adapter, (uiMemoryLoc+uiIndex), (PCHAR)(pBuffer + (uiIndex / 4)), BUFFER_4K);
+ uiNumBytes -= BUFFER_4K;
+ uiIndex += BUFFER_4K;
+ } else {
+ wrm(Adapter, uiMemoryLoc+uiIndex, (PCHAR)(pBuffer + (uiIndex / 4)), uiNumBytes);
+ uiNumBytes = 0;
+ break;
+ }
+ }
+ } else {
+ if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) {
+ ULONG ulBytesTobeSkipped = 0;
+ PUCHAR pcBuffer = (PUCHAR)pBuffer; /* char pointer to take care of odd byte cases. */
+ uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset);
+ ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset);
+ uiOffset += (EEPROM_CALPARAM_START - uiOffset);
+ while (uiNumBytes) {
+ if (uiNumBytes > BUFFER_4K) {
+ wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], BUFFER_4K);
+ uiNumBytes -= BUFFER_4K;
+ uiIndex += BUFFER_4K;
+ } else {
+ wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], uiNumBytes);
+ uiNumBytes = 0;
+ break;
+ }
+ }
+ }
+ }
+ /* restore the values. */
+ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ } else if (Adapter->eNVMType == NVM_EEPROM) {
+ Status = BeceemEEPROMBulkWrite(Adapter,
+ (PUCHAR)pBuffer,
+ uiOffset,
+ uiNumBytes,
+ bVerify);
+ if (bVerify)
+ Status = BeceemEEPROMReadBackandVerify(Adapter, (PUINT)pBuffer, uiOffset, uiNumBytes);
+ } else {
+ Status = -1;
+ }
+ return Status;
+}
+
+/*
+ * Procedure: BcmUpdateSectorSize
+ *
+ * Description: Updates the sector size to FLASH.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * uiSectorSize - sector size
+ *
+ * Returns:
+ * OSAL_STATUS_SUCCESS - if NVM write is successful.
+ * <FAILURE> - if failed.
+ */
+
+int BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, unsigned int uiSectorSize)
+{
+ int Status = -1;
+ struct bcm_flash_cs_info sFlashCsInfo = {0};
+ unsigned int uiTemp = 0;
+ unsigned int uiSectorSig = 0;
+ unsigned int uiCurrentSectorSize = 0;
+ unsigned int value;
+
+ rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ value = 0;
+ wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
+
+ /*
+ * Before updating the sector size in the reserved area, check if already present.
+ */
+ BeceemFlashBulkRead(Adapter, (PUINT)&sFlashCsInfo, Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo));
+ uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig);
+ uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize);
+
+ if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) {
+ if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) {
+ if (uiSectorSize == uiCurrentSectorSize) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Provided sector size is same as programmed in Flash");
+ Status = STATUS_SUCCESS;
+ goto Restore;
+ }
+ }
+ }
+
+ if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) {
+ sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize);
+ sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG);
+
+ Status = BeceemFlashBulkWrite(Adapter,
+ (PUINT)&sFlashCsInfo,
+ Adapter->ulFlashControlSectionStart,
+ sizeof(sFlashCsInfo),
+ TRUE);
+ }
+
+Restore:
+ /* restore the values. */
+ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+
+ return Status;
+}
+
+/*
+ * Procedure: BcmGetFlashSectorSize
+ *
+ * Description: Finds the sector size of the FLASH.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * unsigned int - sector size.
+ *
+ */
+
+static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize)
+{
+ unsigned int uiSectorSize = 0;
+ unsigned int uiSectorSig = 0;
+
+ if (Adapter->bSectorSizeOverride &&
+ (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
+ Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) {
+ Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
+ } else {
+ uiSectorSig = FlashSectorSizeSig;
+
+ if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) {
+ uiSectorSize = FlashSectorSize;
+ /*
+ * If the sector size stored in the FLASH makes sense then use it.
+ */
+ if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) {
+ Adapter->uiSectorSize = uiSectorSize;
+ } else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
+ Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) {
+ /* No valid size in FLASH, check if Config file has it. */
+ Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
+ } else {
+ /* Init to Default, if none of the above works. */
+ Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE;
+ }
+ } else {
+ if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
+ Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)
+ Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
+ else
+ Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE;
+ }
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size :%x\n", Adapter->uiSectorSize);
+
+ return Adapter->uiSectorSize;
+}
+
+/*
+ * Procedure: BcmInitEEPROMQueues
+ *
+ * Description: Initialization of EEPROM queues.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * <OSAL_STATUS_CODE>
+ */
+
+static int BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int value = 0;
+ /* CHIP Bug : Clear the Avail bits on the Read queue. The default
+ * value on this register is supposed to be 0x00001102.
+ * But we get 0x00001122.
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Fixing reset value on 0x0f003004 register\n");
+ value = EEPROM_READ_DATA_AVAIL;
+ wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
+
+ /* Flush the all the EEPROM queues. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n");
+ value = EEPROM_ALL_QUEUE_FLUSH;
+ wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
+
+ value = 0;
+ wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
+
+ /* Read the EEPROM Status Register. Just to see, no real purpose. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter));
+
+ return STATUS_SUCCESS;
+} /* BcmInitEEPROMQueues() */
+
+/*
+ * Procedure: BcmInitNVM
+ *
+ * Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * <OSAL_STATUS_CODE>
+ */
+
+int BcmInitNVM(struct bcm_mini_adapter *ps_adapter)
+{
+ BcmValidateNvmType(ps_adapter);
+ BcmInitEEPROMQueues(ps_adapter);
+
+ if (ps_adapter->eNVMType == NVM_AUTODETECT) {
+ ps_adapter->eNVMType = BcmGetNvmType(ps_adapter);
+ if (ps_adapter->eNVMType == NVM_UNKNOWN)
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n");
+ } else if (ps_adapter->eNVMType == NVM_FLASH) {
+ BcmGetFlashCSInfo(ps_adapter);
+ }
+
+ BcmGetNvmSize(ps_adapter);
+
+ return STATUS_SUCCESS;
+}
+
+/* BcmGetNvmSize : set the EEPROM or flash size in Adapter.
+ *
+ * Input Parameter:
+ * Adapter data structure
+ * Return Value :
+ * 0. means success;
+ */
+
+static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter)
+{
+ if (Adapter->eNVMType == NVM_EEPROM)
+ Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter);
+ else if (Adapter->eNVMType == NVM_FLASH)
+ Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter);
+
+ return 0;
+}
+
+/*
+ * Procedure: BcmValidateNvm
+ *
+ * Description: Validates the NVM Type option selected against the device
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * <VOID>
+ */
+
+static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter)
+{
+ /*
+ * if forcing the FLASH through CFG file, we should ensure device really has a FLASH.
+ * Accessing the FLASH address without the FLASH being present can cause hang/freeze etc.
+ * So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice.
+ */
+
+ if (Adapter->eNVMType == NVM_FLASH &&
+ Adapter->chip_id < 0xBECE3300)
+ Adapter->eNVMType = NVM_AUTODETECT;
+}
+
+/*
+ * Procedure: BcmReadFlashRDID
+ *
+ * Description: Reads ID from Serial Flash
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * Flash ID
+ */
+
+static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter)
+{
+ ULONG ulRDID = 0;
+ unsigned int value;
+
+ /*
+ * Read ID Instruction.
+ */
+ value = (FLASH_CMD_READ_ID << 24);
+ wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
+
+ /* Delay */
+ udelay(10);
+
+ /*
+ * Read SPI READQ REG. The output will be WWXXYYZZ.
+ * The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored.
+ */
+ rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID));
+
+ return ulRDID >> 8;
+}
+
+int BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter)
+{
+ if (!psAdapter) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
+ return -EINVAL;
+ }
+ psAdapter->psFlashCSInfo = kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL);
+ if (psAdapter->psFlashCSInfo == NULL) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x");
+ return -ENOMEM;
+ }
+
+ psAdapter->psFlash2xCSInfo = kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL);
+ if (!psAdapter->psFlash2xCSInfo) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x");
+ kfree(psAdapter->psFlashCSInfo);
+ return -ENOMEM;
+ }
+
+ psAdapter->psFlash2xVendorInfo = kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL);
+ if (!psAdapter->psFlash2xVendorInfo) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x");
+ kfree(psAdapter->psFlashCSInfo);
+ kfree(psAdapter->psFlash2xCSInfo);
+ return -ENOMEM;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+int BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter)
+{
+ if (!psAdapter) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
+ return -EINVAL;
+ }
+ kfree(psAdapter->psFlashCSInfo);
+ kfree(psAdapter->psFlash2xCSInfo);
+ kfree(psAdapter->psFlash2xVendorInfo);
+ return STATUS_SUCCESS;
+}
+
+static int BcmDumpFlash2XCSStructure(struct bcm_flash2x_cs_info *psFlash2xCSInfo, struct bcm_mini_adapter *Adapter)
+{
+ unsigned int Index = 0;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x", (psFlash2xCSInfo->MagicNumber));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End));
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :");
+
+ for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index,
+ (psFlash2xCSInfo->SectorAccessBitMap[Index]));
+
+ return STATUS_SUCCESS;
+}
+
+static int ConvertEndianOf2XCSStructure(struct bcm_flash2x_cs_info *psFlash2xCSInfo)
+{
+ unsigned int Index = 0;
+
+ psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber);
+ psFlash2xCSInfo->FlashLayoutVersion = ntohl(psFlash2xCSInfo->FlashLayoutVersion);
+ /* psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); */
+ psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion);
+ psFlash2xCSInfo->SCSIFirmwareVersion = ntohl(psFlash2xCSInfo->SCSIFirmwareVersion);
+ psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage);
+ psFlash2xCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlash2xCSInfo->OffsetFromZeroForScsiFirmware);
+ psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware);
+ psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage);
+ psFlash2xCSInfo->OffsetFromZeroForDSDStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDStart);
+ psFlash2xCSInfo->OffsetFromZeroForDSDEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDEnd);
+ psFlash2xCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAStart);
+ psFlash2xCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAEnd);
+ psFlash2xCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionStart);
+ psFlash2xCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionData);
+ psFlash2xCSInfo->CDLessInactivityTimeout = ntohl(psFlash2xCSInfo->CDLessInactivityTimeout);
+ psFlash2xCSInfo->NewImageSignature = ntohl(psFlash2xCSInfo->NewImageSignature);
+ psFlash2xCSInfo->FlashSectorSizeSig = ntohl(psFlash2xCSInfo->FlashSectorSizeSig);
+ psFlash2xCSInfo->FlashSectorSize = ntohl(psFlash2xCSInfo->FlashSectorSize);
+ psFlash2xCSInfo->FlashWriteSupportSize = ntohl(psFlash2xCSInfo->FlashWriteSupportSize);
+ psFlash2xCSInfo->TotalFlashSize = ntohl(psFlash2xCSInfo->TotalFlashSize);
+ psFlash2xCSInfo->FlashBaseAddr = ntohl(psFlash2xCSInfo->FlashBaseAddr);
+ psFlash2xCSInfo->FlashPartMaxSize = ntohl(psFlash2xCSInfo->FlashPartMaxSize);
+ psFlash2xCSInfo->IsCDLessDeviceBootSig = ntohl(psFlash2xCSInfo->IsCDLessDeviceBootSig);
+ psFlash2xCSInfo->MassStorageTimeout = ntohl(psFlash2xCSInfo->MassStorageTimeout);
+ psFlash2xCSInfo->OffsetISOImage1Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1Start);
+ psFlash2xCSInfo->OffsetISOImage1Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1End);
+ psFlash2xCSInfo->OffsetISOImage1Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2Start);
+ psFlash2xCSInfo->OffsetISOImage1Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2End);
+ psFlash2xCSInfo->OffsetISOImage1Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3Start);
+ psFlash2xCSInfo->OffsetISOImage1Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3End);
+ psFlash2xCSInfo->OffsetISOImage2Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1Start);
+ psFlash2xCSInfo->OffsetISOImage2Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1End);
+ psFlash2xCSInfo->OffsetISOImage2Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2Start);
+ psFlash2xCSInfo->OffsetISOImage2Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2End);
+ psFlash2xCSInfo->OffsetISOImage2Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3Start);
+ psFlash2xCSInfo->OffsetISOImage2Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3End);
+ psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader = ntohl(psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader);
+ psFlash2xCSInfo->OffsetFromZeroForDSD1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1Start);
+ psFlash2xCSInfo->OffsetFromZeroForDSD1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1End);
+ psFlash2xCSInfo->OffsetFromZeroForDSD2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2Start);
+ psFlash2xCSInfo->OffsetFromZeroForDSD2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2End);
+ psFlash2xCSInfo->OffsetFromZeroForVSA1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1Start);
+ psFlash2xCSInfo->OffsetFromZeroForVSA1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1End);
+ psFlash2xCSInfo->OffsetFromZeroForVSA2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2Start);
+ psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End);
+
+ for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++)
+ psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]);
+
+ return STATUS_SUCCESS;
+}
+
+static int ConvertEndianOfCSStructure(struct bcm_flash_cs_info *psFlashCSInfo)
+{
+ /* unsigned int Index = 0; */
+ psFlashCSInfo->MagicNumber = ntohl(psFlashCSInfo->MagicNumber);
+ psFlashCSInfo->FlashLayoutVersion = ntohl(psFlashCSInfo->FlashLayoutVersion);
+ psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion);
+ /* won't convert according to old assumption */
+ psFlashCSInfo->SCSIFirmwareVersion = (psFlashCSInfo->SCSIFirmwareVersion);
+ psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage);
+ psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware);
+ psFlashCSInfo->SizeOfScsiFirmware = ntohl(psFlashCSInfo->SizeOfScsiFirmware);
+ psFlashCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage);
+ psFlashCSInfo->OffsetFromZeroForCalibrationStart = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationStart);
+ psFlashCSInfo->OffsetFromZeroForCalibrationEnd = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationEnd);
+ psFlashCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart);
+ psFlashCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd);
+ psFlashCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionStart);
+ psFlashCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionData);
+ psFlashCSInfo->CDLessInactivityTimeout = ntohl(psFlashCSInfo->CDLessInactivityTimeout);
+ psFlashCSInfo->NewImageSignature = ntohl(psFlashCSInfo->NewImageSignature);
+ psFlashCSInfo->FlashSectorSizeSig = ntohl(psFlashCSInfo->FlashSectorSizeSig);
+ psFlashCSInfo->FlashSectorSize = ntohl(psFlashCSInfo->FlashSectorSize);
+ psFlashCSInfo->FlashWriteSupportSize = ntohl(psFlashCSInfo->FlashWriteSupportSize);
+ psFlashCSInfo->TotalFlashSize = ntohl(psFlashCSInfo->TotalFlashSize);
+ psFlashCSInfo->FlashBaseAddr = ntohl(psFlashCSInfo->FlashBaseAddr);
+ psFlashCSInfo->FlashPartMaxSize = ntohl(psFlashCSInfo->FlashPartMaxSize);
+ psFlashCSInfo->IsCDLessDeviceBootSig = ntohl(psFlashCSInfo->IsCDLessDeviceBootSig);
+ psFlashCSInfo->MassStorageTimeout = ntohl(psFlashCSInfo->MassStorageTimeout);
+
+ return STATUS_SUCCESS;
+}
+
+static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
+{
+ return (Adapter->uiVendorExtnFlag &&
+ (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) &&
+ (Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS));
+}
+
+static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter)
+{
+ B_UINT32 i = 0;
+ unsigned int uiSizeSection = 0;
+
+ Adapter->uiVendorExtnFlag = false;
+
+ for (i = 0; i < TOTAL_SECTIONS; i++)
+ Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart = UNINIT_PTR_IN_CS;
+
+ if (STATUS_SUCCESS != vendorextnGetSectionInfo(Adapter, Adapter->psFlash2xVendorInfo))
+ return;
+
+ i = 0;
+ while (i < TOTAL_SECTIONS) {
+ if (!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) {
+ i++;
+ continue;
+ }
+
+ Adapter->uiVendorExtnFlag = TRUE;
+ uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd -
+ Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart);
+
+ switch (i) {
+ case DSD0:
+ if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) &&
+ (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart))
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS;
+ else
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS;
+ break;
+
+ case DSD1:
+ if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) &&
+ (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart))
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS;
+ else
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS;
+ break;
+
+ case DSD2:
+ if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) &&
+ (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart))
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS;
+ else
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS;
+ break;
+ case VSA0:
+ if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS;
+ else
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS;
+ break;
+
+ case VSA1:
+ if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS;
+ else
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS;
+ break;
+ case VSA2:
+ if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS;
+ else
+ Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS;
+ break;
+
+ default:
+ break;
+ }
+ i++;
+ }
+}
+
+/*
+ * Procedure: BcmGetFlashCSInfo
+ *
+ * Description: Reads control structure and gets Cal section addresses.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * <VOID>
+ */
+
+static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter)
+{
+ /* struct bcm_flash_cs_info sFlashCsInfo = {0}; */
+
+ #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
+ unsigned int value;
+ #endif
+
+ unsigned int uiFlashLayoutMajorVersion;
+ Adapter->uiFlashLayoutMinorVersion = 0;
+ Adapter->uiFlashLayoutMajorVersion = 0;
+ Adapter->ulFlashControlSectionStart = FLASH_CS_INFO_START_ADDR;
+
+ Adapter->uiFlashBaseAdd = 0;
+ Adapter->ulFlashCalStart = 0;
+ memset(Adapter->psFlashCSInfo, 0 , sizeof(struct bcm_flash_cs_info));
+ memset(Adapter->psFlash2xCSInfo, 0 , sizeof(struct bcm_flash2x_cs_info));
+
+ if (!Adapter->bDDRInitDone) {
+ value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
+ wrmalt(Adapter, 0xAF00A080, &value, sizeof(value));
+ }
+
+ /* Reading first 8 Bytes to get the Flash Layout
+ * MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes)
+ */
+ BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, 8);
+
+ Adapter->psFlashCSInfo->FlashLayoutVersion = ntohl(Adapter->psFlashCSInfo->FlashLayoutVersion);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion));
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber));
+
+ if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) {
+ uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion));
+ Adapter->uiFlashLayoutMinorVersion = MINOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion));
+ } else {
+ Adapter->uiFlashLayoutMinorVersion = 0;
+ uiFlashLayoutMajorVersion = 0;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion);
+
+ if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) {
+ BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, sizeof(struct bcm_flash_cs_info));
+ ConvertEndianOfCSStructure(Adapter->psFlashCSInfo);
+ Adapter->ulFlashCalStart = (Adapter->psFlashCSInfo->OffsetFromZeroForCalibrationStart);
+
+ if (!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
+ Adapter->ulFlashControlSectionStart = Adapter->psFlashCSInfo->OffsetFromZeroForControlSectionStart;
+
+ if ((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) &&
+ (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) &&
+ (FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) &&
+ (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) {
+ Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize);
+ Adapter->fpFlashWrite = flashByteWrite;
+ Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus;
+ } else {
+ Adapter->ulFlashWriteSize = MAX_RW_SIZE;
+ Adapter->fpFlashWrite = flashWrite;
+ Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus;
+ }
+
+ BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig),
+ (Adapter->psFlashCSInfo->FlashSectorSize));
+ Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF;
+ } else {
+ if (BcmFlash2xBulkRead(Adapter, (PUINT)Adapter->psFlash2xCSInfo, NO_SECTION_VAL,
+ Adapter->ulFlashControlSectionStart, sizeof(struct bcm_flash2x_cs_info))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure\n");
+ return STATUS_FAILURE;
+ }
+
+ ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo);
+ BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo, Adapter);
+ if ((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) &&
+ (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) &&
+ (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) &&
+ (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) {
+ Adapter->ulFlashWriteSize = Adapter->psFlash2xCSInfo->FlashWriteSupportSize;
+ Adapter->fpFlashWrite = flashByteWrite;
+ Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus;
+ } else {
+ Adapter->ulFlashWriteSize = MAX_RW_SIZE;
+ Adapter->fpFlashWrite = flashWrite;
+ Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus;
+ }
+
+ BcmGetFlashSectorSize(Adapter, Adapter->psFlash2xCSInfo->FlashSectorSizeSig,
+ Adapter->psFlash2xCSInfo->FlashSectorSize);
+
+ UpdateVendorInfo(Adapter);
+
+ BcmGetActiveDSD(Adapter);
+ BcmGetActiveISO(Adapter);
+ Adapter->uiFlashBaseAdd = Adapter->psFlash2xCSInfo->FlashBaseAddr & 0xFCFFFFFF;
+ Adapter->ulFlashControlSectionStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart;
+ }
+ /*
+ * Concerns: what if CS sector size does not match with this sector size ???
+ * what is the indication of AccessBitMap in CS in flash 2.x ????
+ */
+ Adapter->ulFlashID = BcmReadFlashRDID(Adapter);
+ Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion;
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Procedure: BcmGetNvmType
+ *
+ * Description: Finds the type of NVM used.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ *
+ * Returns:
+ * NVM_TYPE
+ *
+ */
+
+static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiData = 0;
+
+ BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4);
+ if (uiData == BECM)
+ return NVM_EEPROM;
+
+ /*
+ * Read control struct and get cal addresses before accessing the flash
+ */
+ BcmGetFlashCSInfo(Adapter);
+
+ BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4);
+ if (uiData == BECM)
+ return NVM_FLASH;
+
+ /*
+ * even if there is no valid signature on EEPROM/FLASH find out if they really exist.
+ * if exist select it.
+ */
+ if (BcmGetEEPROMSize(Adapter))
+ return NVM_EEPROM;
+
+ /* TBD for Flash. */
+ return NVM_UNKNOWN;
+}
+
+/*
+ * BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given
+ * @Adapter : Drivers Private Data structure
+ * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val
+ *
+ * Return value:-
+ * On success it return the start offset of the provided section val
+ * On Failure -returns STATUS_FAILURE
+ */
+
+int BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal)
+{
+ /*
+ * Considering all the section for which end offset can be calculated or directly given
+ * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section
+ * endoffset can't be calculated or given in CS Structure.
+ */
+
+ int SectStartOffset = 0;
+
+ SectStartOffset = INVALID_OFFSET;
+
+ if (IsSectionExistInVendorInfo(Adapter, eFlashSectionVal))
+ return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart;
+
+ switch (eFlashSectionVal) {
+ case ISO_IMAGE1:
+ if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) &&
+ (IsNonCDLessDevice(Adapter) == false))
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start);
+ break;
+ case ISO_IMAGE2:
+ if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) &&
+ (IsNonCDLessDevice(Adapter) == false))
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start);
+ break;
+ case DSD0:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart);
+ break;
+ case DSD1:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start);
+ break;
+ case DSD2:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start);
+ break;
+ case VSA0:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart);
+ break;
+ case VSA1:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start);
+ break;
+ case VSA2:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start);
+ break;
+ case SCSI:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware);
+ break;
+ case CONTROL_SECTION:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart);
+ break;
+ case ISO_IMAGE1_PART2:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start);
+ break;
+ case ISO_IMAGE1_PART3:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);
+ break;
+ case ISO_IMAGE2_PART2:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start);
+ break;
+ case ISO_IMAGE2_PART3:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS)
+ SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
+ SectStartOffset = INVALID_OFFSET;
+ }
+
+ return SectStartOffset;
+}
+
+/*
+ * BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given
+ * @Adapter : Drivers Private Data structure
+ * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val
+ *
+ * Return value:-
+ * On success it return the end offset of the provided section val
+ * On Failure -returns STATUS_FAILURE
+ */
+
+static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
+{
+ int SectEndOffset = 0;
+
+ SectEndOffset = INVALID_OFFSET;
+ if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
+ return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd;
+
+ switch (eFlash2xSectionVal) {
+ case ISO_IMAGE1:
+ if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) &&
+ (IsNonCDLessDevice(Adapter) == false))
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End);
+ break;
+ case ISO_IMAGE2:
+ if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) &&
+ (IsNonCDLessDevice(Adapter) == false))
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End);
+ break;
+ case DSD0:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd);
+ break;
+ case DSD1:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End);
+ break;
+ case DSD2:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End);
+ break;
+ case VSA0:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd);
+ break;
+ case VSA1:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End);
+ break;
+ case VSA2:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End);
+ break;
+ case SCSI:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS)
+ SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) +
+ (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware));
+ break;
+ case CONTROL_SECTION:
+ /* Not Clear So Putting failure. confirm and fix it. */
+ SectEndOffset = STATUS_FAILURE;
+ break;
+ case ISO_IMAGE1_PART2:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End);
+ break;
+ case ISO_IMAGE1_PART3:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End);
+ break;
+ case ISO_IMAGE2_PART2:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End);
+ break;
+ case ISO_IMAGE2_PART3:
+ if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End != UNINIT_PTR_IN_CS)
+ SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End);
+ break;
+ default:
+ SectEndOffset = INVALID_OFFSET;
+ }
+
+ return SectEndOffset;
+}
+
+/*
+ * BcmFlash2xBulkRead:- Read API for Flash Map 2.x .
+ * @Adapter :Driver Private Data Structure
+ * @pBuffer : Buffer where data has to be put after reading
+ * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val
+ * @uiOffsetWithinSectionVal :- Offset with in provided section
+ * @uiNumBytes : Number of Bytes for Read
+ *
+ * Return value:-
+ * return true on success and STATUS_FAILURE on fail.
+ */
+
+int BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ enum bcm_flash2x_section_val eFlash2xSectionVal,
+ unsigned int uiOffsetWithinSectionVal,
+ unsigned int uiNumBytes)
+{
+ int Status = STATUS_SUCCESS;
+ int SectionStartOffset = 0;
+ unsigned int uiAbsoluteOffset = 0;
+ unsigned int uiTemp = 0, value = 0;
+
+ if (!Adapter) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL");
+ return -EINVAL;
+ }
+ if (Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed");
+ return -ENODEV;
+ }
+
+ /* NO_SECTION_VAL means absolute offset is given. */
+ if (eFlash2xSectionVal == NO_SECTION_VAL)
+ SectionStartOffset = 0;
+ else
+ SectionStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
+
+ if (SectionStartOffset == STATUS_FAILURE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exist in Flash 2.x Map ", eFlash2xSectionVal);
+ return -EINVAL;
+ }
+
+ if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
+ return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes);
+
+ /* calculating the absolute offset from FLASH; */
+ uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset;
+ rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ value = 0;
+ wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
+ Status = BeceemFlashBulkRead(Adapter, pBuffer, uiAbsoluteOffset, uiNumBytes);
+ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status);
+ return Status;
+ }
+
+ return Status;
+}
+
+/*
+ * BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x.
+ * @Adapter :Driver Private Data Structure
+ * @pBuffer : Buffer From where data has to taken for writing
+ * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val
+ * @uiOffsetWithinSectionVal :- Offset with in provided section
+ * @uiNumBytes : Number of Bytes for Write
+ *
+ * Return value:-
+ * return true on success and STATUS_FAILURE on fail.
+ *
+ */
+
+int BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter,
+ PUINT pBuffer,
+ enum bcm_flash2x_section_val eFlash2xSectVal,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes,
+ unsigned int bVerify)
+{
+ int Status = STATUS_SUCCESS;
+ unsigned int FlashSectValStartOffset = 0;
+ unsigned int uiTemp = 0, value = 0;
+
+ if (!Adapter) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL");
+ return -EINVAL;
+ }
+
+ if (Adapter->device_removed) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed");
+ return -ENODEV;
+ }
+
+ /* NO_SECTION_VAL means absolute offset is given. */
+ if (eFlash2xSectVal == NO_SECTION_VAL)
+ FlashSectValStartOffset = 0;
+ else
+ FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectVal);
+
+ if (FlashSectValStartOffset == STATUS_FAILURE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exist in Flash Map 2.x", eFlash2xSectVal);
+ return -EINVAL;
+ }
+
+ if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectVal))
+ return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify);
+
+ /* calculating the absolute offset from FLASH; */
+ uiOffset = uiOffset + FlashSectValStartOffset;
+
+ rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ value = 0;
+ wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
+
+ Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiOffset, uiNumBytes, bVerify);
+
+ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status);
+ return Status;
+ }
+
+ return Status;
+}
+
+/*
+ * BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR
+ * @Adapter :-Drivers private Data Structure
+ *
+ * Return Value:-
+ * Return STATUS_SUCESS if get success in setting the right DSD else negative error code
+ *
+ */
+
+static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter)
+{
+ enum bcm_flash2x_section_val uiHighestPriDSD = 0;
+
+ uiHighestPriDSD = getHighestPriDSD(Adapter);
+ Adapter->eActiveDSD = uiHighestPriDSD;
+
+ if (DSD0 == uiHighestPriDSD)
+ Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart;
+ if (DSD1 == uiHighestPriDSD)
+ Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start;
+ if (DSD2 == uiHighestPriDSD)
+ Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start;
+ if (Adapter->eActiveDSD)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD);
+ if (Adapter->eActiveDSD == 0) {
+ /* if No DSD gets Active, Make Active the DSD with WR permission */
+ if (IsSectionWritable(Adapter, DSD2)) {
+ Adapter->eActiveDSD = DSD2;
+ Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start;
+ } else if (IsSectionWritable(Adapter, DSD1)) {
+ Adapter->eActiveDSD = DSD1;
+ Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start;
+ } else if (IsSectionWritable(Adapter, DSD0)) {
+ Adapter->eActiveDSD = DSD0;
+ Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue
+ * @Adapter : Driver private Data Structure
+ *
+ * Return Value:-
+ * Sucsess:- STATUS_SUCESS
+ * Failure- : negative erro code
+ *
+ */
+
+static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter)
+{
+ int HighestPriISO = 0;
+
+ HighestPriISO = getHighestPriISO(Adapter);
+
+ Adapter->eActiveISO = HighestPriISO;
+ if (Adapter->eActiveISO == ISO_IMAGE2)
+ Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start);
+ else if (Adapter->eActiveISO == ISO_IMAGE1)
+ Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start);
+
+ if (Adapter->eActiveISO)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active ISO :%x", Adapter->eActiveISO);
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * IsOffsetWritable :- it will tell the access permission of the sector having passed offset
+ * @Adapter : Drivers Private Data Structure
+ * @uiOffset : Offset provided in the Flash
+ *
+ * Return Value:-
+ * Success:-TRUE , offset is writable
+ * Failure:-false, offset is RO
+ *
+ */
+
+static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset)
+{
+ unsigned int uiSectorNum = 0;
+ unsigned int uiWordOfSectorPermission = 0;
+ unsigned int uiBitofSectorePermission = 0;
+ B_UINT32 permissionBits = 0;
+
+ uiSectorNum = uiOffset/Adapter->uiSectorSize;
+
+ /* calculating the word having this Sector Access permission from SectorAccessBitMap Array */
+ uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum / 16];
+
+ /* calculating the bit index inside the word for this sector */
+ uiBitofSectorePermission = 2 * (15 - uiSectorNum % 16);
+
+ /* Setting Access permission */
+ permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission);
+ permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3;
+ if (permissionBits == SECTOR_READWRITE_PERMISSION)
+ return TRUE;
+ else
+ return false;
+}
+
+static int BcmDumpFlash2xSectionBitMap(struct bcm_flash2x_bitmap *psFlash2xBitMap)
+{
+ struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD0 :0X%x", psFlash2xBitMap->DSD0);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD1 :0X%x", psFlash2xBitMap->DSD1);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD2 :0X%x", psFlash2xBitMap->DSD2);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA0 :0X%x", psFlash2xBitMap->VSA0);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA1 :0X%x", psFlash2xBitMap->VSA1);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA2 :0X%x", psFlash2xBitMap->VSA2);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSI :0X%x", psFlash2xBitMap->SCSI);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CONTROL_SECTION :0X%x", psFlash2xBitMap->CONTROL_SECTION);
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash
+ * 8bit has been assigned to every section.
+ * bit[0] :Section present or not
+ * bit[1] :section is valid or not
+ * bit[2] : Secton is read only or has write permission too.
+ * bit[3] : Active Section -
+ * bit[7...4] = Reserved .
+ *
+ * @Adapter:-Driver private Data Structure
+ *
+ * Return value:-
+ * Success:- STATUS_SUCESS
+ * Failure:- negative error code
+ */
+
+int BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap)
+{
+ struct bcm_flash2x_cs_info *psFlash2xCSInfo = Adapter->psFlash2xCSInfo;
+ enum bcm_flash2x_section_val uiHighestPriDSD = 0;
+ enum bcm_flash2x_section_val uiHighestPriISO = 0;
+ bool SetActiveDSDDone = false;
+ bool SetActiveISODone = false;
+
+ /* For 1.x map all the section except DSD0 will be shown as not present
+ * This part will be used by calibration tool to detect the number of DSD present in Flash.
+ */
+ if (IsFlash2x(Adapter) == false) {
+ psFlash2xBitMap->ISO_IMAGE2 = 0;
+ psFlash2xBitMap->ISO_IMAGE1 = 0;
+ psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; /* 0xF; 0000(Reseved)1(Active)0(RW)1(valid)1(present) */
+ psFlash2xBitMap->DSD1 = 0;
+ psFlash2xBitMap->DSD2 = 0;
+ psFlash2xBitMap->VSA0 = 0;
+ psFlash2xBitMap->VSA1 = 0;
+ psFlash2xBitMap->VSA2 = 0;
+ psFlash2xBitMap->CONTROL_SECTION = 0;
+ psFlash2xBitMap->SCSI = 0;
+ psFlash2xBitMap->Reserved0 = 0;
+ psFlash2xBitMap->Reserved1 = 0;
+ psFlash2xBitMap->Reserved2 = 0;
+
+ return STATUS_SUCCESS;
+ }
+
+ uiHighestPriDSD = getHighestPriDSD(Adapter);
+ uiHighestPriISO = getHighestPriISO(Adapter);
+
+ /*
+ * IS0 IMAGE 2
+ */
+ if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT;
+
+ if (ReadISOSignature(Adapter, ISO_IMAGE2) == ISO_IMAGE_MAGIC_NUMBER)
+ psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID;
+
+ /* Calculation for extrating the Access permission */
+ if (IsSectionWritable(Adapter, ISO_IMAGE2) == false)
+ psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO;
+
+ if (SetActiveISODone == false && uiHighestPriISO == ISO_IMAGE2) {
+ psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT;
+ SetActiveISODone = TRUE;
+ }
+ }
+
+ /*
+ * IS0 IMAGE 1
+ */
+ if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT;
+
+ if (ReadISOSignature(Adapter, ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER)
+ psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID;
+
+ /* Calculation for extrating the Access permission */
+ if (IsSectionWritable(Adapter, ISO_IMAGE1) == false)
+ psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO;
+
+ if (SetActiveISODone == false && uiHighestPriISO == ISO_IMAGE1) {
+ psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT;
+ SetActiveISODone = TRUE;
+ }
+ }
+
+ /*
+ * DSD2
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT;
+
+ if (ReadDSDSignature(Adapter, DSD2) == DSD_IMAGE_MAGIC_NUMBER)
+ psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID;
+
+ /* Calculation for extrating the Access permission */
+ if (IsSectionWritable(Adapter, DSD2) == false) {
+ psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO;
+ } else {
+ /* Means section is writable */
+ if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD2)) {
+ psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT;
+ SetActiveDSDDone = TRUE;
+ }
+ }
+ }
+
+ /*
+ * DSD 1
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT;
+
+ if (ReadDSDSignature(Adapter, DSD1) == DSD_IMAGE_MAGIC_NUMBER)
+ psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID;
+
+ /* Calculation for extrating the Access permission */
+ if (IsSectionWritable(Adapter, DSD1) == false) {
+ psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO;
+ } else {
+ /* Means section is writable */
+ if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD1)) {
+ psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT;
+ SetActiveDSDDone = TRUE;
+ }
+ }
+ }
+
+ /*
+ * For DSD 0
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT;
+
+ if (ReadDSDSignature(Adapter, DSD0) == DSD_IMAGE_MAGIC_NUMBER)
+ psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID;
+
+ /* Setting Access permission */
+ if (IsSectionWritable(Adapter, DSD0) == false) {
+ psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO;
+ } else {
+ /* Means section is writable */
+ if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD0)) {
+ psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT;
+ SetActiveDSDDone = TRUE;
+ }
+ }
+ }
+
+ /*
+ * VSA 0
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT;
+
+ /* Setting the Access Bit. Map is not defined hece setting it always valid */
+ psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID;
+
+ /* Calculation for extrating the Access permission */
+ if (IsSectionWritable(Adapter, VSA0) == false)
+ psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_RO;
+
+ /* By Default section is Active */
+ psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT;
+ }
+
+ /*
+ * VSA 1
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT;
+
+ /* Setting the Access Bit. Map is not defined hece setting it always valid */
+ psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID;
+
+ /* Checking For Access permission */
+ if (IsSectionWritable(Adapter, VSA1) == false)
+ psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO;
+
+ /* By Default section is Active */
+ psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT;
+ }
+
+ /*
+ * VSA 2
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT;
+
+ /* Setting the Access Bit. Map is not defined hece setting it always valid */
+ psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID;
+
+ /* Checking For Access permission */
+ if (IsSectionWritable(Adapter, VSA2) == false)
+ psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO;
+
+ /* By Default section is Active */
+ psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT;
+ }
+
+ /*
+ * SCSI Section
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT;
+
+ /* Setting the Access Bit. Map is not defined hece setting it always valid */
+ psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID;
+
+ /* Checking For Access permission */
+ if (IsSectionWritable(Adapter, SCSI) == false)
+ psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO;
+
+ /* By Default section is Active */
+ psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT;
+ }
+
+ /*
+ * Control Section
+ */
+ if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) {
+ /* Setting the 0th Bit representing the Section is present or not. */
+ psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT);
+
+ /* Setting the Access Bit. Map is not defined hece setting it always valid */
+ psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID;
+
+ /* Checking For Access permission */
+ if (IsSectionWritable(Adapter, CONTROL_SECTION) == false)
+ psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO;
+
+ /* By Default section is Active */
+ psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT;
+ }
+
+ /*
+ * For Reserved Sections
+ */
+ psFlash2xBitMap->Reserved0 = 0;
+ psFlash2xBitMap->Reserved0 = 0;
+ psFlash2xBitMap->Reserved0 = 0;
+ BcmDumpFlash2xSectionBitMap(psFlash2xBitMap);
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * BcmSetActiveSection :- Set Active section is used to make priority field highest over other
+ * section of same type.
+ *
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @eFlash2xSectionVal :- Flash section val whose priority has to be made highest.
+ *
+ * Return Value:- Make the priorit highest else return erorr code
+ *
+ */
+
+int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal)
+{
+ unsigned int SectImagePriority = 0;
+ int Status = STATUS_SUCCESS;
+
+ /* struct bcm_dsd_header sDSD = {0};
+ * struct bcm_iso_header sISO = {0};
+ */
+ int HighestPriDSD = 0;
+ int HighestPriISO = 0;
+
+ Status = IsSectionWritable(Adapter, eFlash2xSectVal);
+ if (Status != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section <%d> is not writable", eFlash2xSectVal);
+ return STATUS_FAILURE;
+ }
+
+ Adapter->bHeaderChangeAllowed = TRUE;
+ switch (eFlash2xSectVal) {
+ case ISO_IMAGE1:
+ case ISO_IMAGE2:
+ if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) {
+ HighestPriISO = getHighestPriISO(Adapter);
+
+ if (HighestPriISO == eFlash2xSectVal) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1;
+
+ if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) {
+ /* This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF.
+ * We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO
+ * by user
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal);
+ SectImagePriority = htonl(0x1);
+ Status = BcmFlash2xBulkWrite(Adapter,
+ &SectImagePriority,
+ HighestPriISO,
+ 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority),
+ SIGNATURE_SIZE,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
+ Status = STATUS_FAILURE;
+ break;
+ }
+
+ HighestPriISO = getHighestPriISO(Adapter);
+
+ if (HighestPriISO == eFlash2xSectVal) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ SectImagePriority = 2;
+ }
+
+ SectImagePriority = htonl(SectImagePriority);
+
+ Status = BcmFlash2xBulkWrite(Adapter,
+ &SectImagePriority,
+ eFlash2xSectVal,
+ 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority),
+ SIGNATURE_SIZE,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
+ break;
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority");
+ Status = STATUS_FAILURE;
+ break;
+ }
+ break;
+ case DSD0:
+ case DSD1:
+ case DSD2:
+ if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) {
+ HighestPriDSD = getHighestPriDSD(Adapter);
+ if (HighestPriDSD == eFlash2xSectVal) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1;
+ if (SectImagePriority <= 0) {
+ /* This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF.
+ * We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD
+ * by user
+ */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal);
+ SectImagePriority = htonl(0x1);
+
+ Status = BcmFlash2xBulkWrite(Adapter,
+ &SectImagePriority,
+ HighestPriDSD,
+ Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
+ SIGNATURE_SIZE,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
+ break;
+ }
+
+ HighestPriDSD = getHighestPriDSD(Adapter);
+
+ if (HighestPriDSD == eFlash2xSectVal) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal);
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ SectImagePriority = htonl(0x2);
+ Status = BcmFlash2xBulkWrite(Adapter,
+ &SectImagePriority,
+ HighestPriDSD,
+ Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
+ SIGNATURE_SIZE,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
+ break;
+ }
+
+ HighestPriDSD = getHighestPriDSD(Adapter);
+ if (HighestPriDSD == eFlash2xSectVal) {
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ SectImagePriority = 3;
+ }
+ SectImagePriority = htonl(SectImagePriority);
+ Status = BcmFlash2xBulkWrite(Adapter,
+ &SectImagePriority,
+ eFlash2xSectVal,
+ Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
+ SIGNATURE_SIZE,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
+ Status = STATUS_FAILURE;
+ break;
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority");
+ Status = STATUS_FAILURE;
+ break;
+ }
+ break;
+ case VSA0:
+ case VSA1:
+ case VSA2:
+ /* Has to be decided */
+ break;
+ default:
+ Status = STATUS_FAILURE;
+ break;
+ }
+
+ Adapter->bHeaderChangeAllowed = false;
+ return Status;
+}
+
+/*
+ * BcmCopyISO - Used only for copying the ISO section
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @sCopySectStrut :- Section copy structure
+ *
+ * Return value:- SUCCESS if copies successfully else negative error code
+ *
+ */
+
+int BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut)
+{
+ PCHAR Buff = NULL;
+ enum bcm_flash2x_section_val eISOReadPart = 0, eISOWritePart = 0;
+ unsigned int uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0;
+ unsigned int uiTotalDataToCopy = 0;
+ bool IsThisHeaderSector = false;
+ unsigned int sigOffset = 0;
+ unsigned int ISOLength = 0;
+ unsigned int Status = STATUS_SUCCESS;
+ unsigned int SigBuff[MAX_RW_SIZE];
+ unsigned int i = 0;
+
+ if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
+ return STATUS_FAILURE;
+ }
+
+ Status = BcmFlash2xBulkRead(Adapter,
+ &ISOLength,
+ sCopySectStrut.SrcSection,
+ 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageSize),
+ 4);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n");
+ return Status;
+ }
+
+ ISOLength = htonl(ISOLength);
+ if (ISOLength % Adapter->uiSectorSize)
+ ISOLength = Adapter->uiSectorSize * (1 + ISOLength/Adapter->uiSectorSize);
+
+ sigOffset = FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber);
+
+ Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL);
+
+ if (!Buff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for section size");
+ return -ENOMEM;
+ }
+
+ if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) {
+ eISOReadPart = ISO_IMAGE1;
+ eISOWritePart = ISO_IMAGE2;
+ uiReadOffsetWithinPart = 0;
+ uiWriteOffsetWithinPart = 0;
+
+ uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);
+
+ if (uiTotalDataToCopy < ISOLength) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
+ Status = STATUS_FAILURE;
+ goto out;
+ }
+
+ uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);
+
+ if (uiTotalDataToCopy < ISOLength) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size");
+ Status = STATUS_FAILURE;
+ goto out;
+ }
+
+ uiTotalDataToCopy = ISOLength;
+
+ CorruptISOSig(Adapter, ISO_IMAGE2);
+ while (uiTotalDataToCopy) {
+ if (uiTotalDataToCopy == Adapter->uiSectorSize) {
+ /* Setting for write of first sector. First sector is assumed to be written in last */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector");
+ eISOReadPart = ISO_IMAGE1;
+ uiReadOffsetWithinPart = 0;
+ eISOWritePart = ISO_IMAGE2;
+ uiWriteOffsetWithinPart = 0;
+ IsThisHeaderSector = TRUE;
+ } else {
+ uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize;
+ uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize;
+
+ if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) {
+ eISOReadPart = ISO_IMAGE1_PART2;
+ uiReadOffsetWithinPart = 0;
+ }
+
+ if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) {
+ eISOReadPart = ISO_IMAGE1_PART3;
+ uiReadOffsetWithinPart = 0;
+ }
+
+ if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) {
+ eISOWritePart = ISO_IMAGE2_PART2;
+ uiWriteOffsetWithinPart = 0;
+ }
+
+ if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) {
+ eISOWritePart = ISO_IMAGE2_PART3;
+ uiWriteOffsetWithinPart = 0;
+ }
+ }
+
+ Status = BcmFlash2xBulkRead(Adapter,
+ (PUINT)Buff,
+ eISOReadPart,
+ uiReadOffsetWithinPart,
+ Adapter->uiSectorSize);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart);
+ break;
+ }
+
+ if (IsThisHeaderSector == TRUE) {
+ /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
+ memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);
+
+ for (i = 0; i < MAX_RW_SIZE; i++)
+ *(Buff + sigOffset + i) = 0xFF;
+ }
+ Adapter->bHeaderChangeAllowed = TRUE;
+ Status = BcmFlash2xBulkWrite(Adapter,
+ (PUINT)Buff,
+ eISOWritePart,
+ uiWriteOffsetWithinPart,
+ Adapter->uiSectorSize,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart);
+ break;
+ }
+
+ Adapter->bHeaderChangeAllowed = false;
+ if (IsThisHeaderSector == TRUE) {
+ WriteToFlashWithoutSectorErase(Adapter,
+ SigBuff,
+ eISOWritePart,
+ sigOffset,
+ MAX_RW_SIZE);
+ IsThisHeaderSector = false;
+ }
+ /* subtracting the written Data */
+ uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
+ }
+ }
+
+ if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) {
+ eISOReadPart = ISO_IMAGE2;
+ eISOWritePart = ISO_IMAGE1;
+ uiReadOffsetWithinPart = 0;
+ uiWriteOffsetWithinPart = 0;
+
+ uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);
+
+ if (uiTotalDataToCopy < ISOLength) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
+ Status = STATUS_FAILURE;
+ goto out;
+ }
+
+ uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) +
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) -
+ (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);
+
+ if (uiTotalDataToCopy < ISOLength) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size");
+ Status = STATUS_FAILURE;
+ goto out;
+ }
+
+ uiTotalDataToCopy = ISOLength;
+
+ CorruptISOSig(Adapter, ISO_IMAGE1);
+
+ while (uiTotalDataToCopy) {
+ if (uiTotalDataToCopy == Adapter->uiSectorSize) {
+ /* Setting for write of first sector. First sector is assumed to be written in last */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector");
+ eISOReadPart = ISO_IMAGE2;
+ uiReadOffsetWithinPart = 0;
+ eISOWritePart = ISO_IMAGE1;
+ uiWriteOffsetWithinPart = 0;
+ IsThisHeaderSector = TRUE;
+ } else {
+ uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize;
+ uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize;
+
+ if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) {
+ eISOReadPart = ISO_IMAGE2_PART2;
+ uiReadOffsetWithinPart = 0;
+ }
+
+ if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) {
+ eISOReadPart = ISO_IMAGE2_PART3;
+ uiReadOffsetWithinPart = 0;
+ }
+
+ if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) {
+ eISOWritePart = ISO_IMAGE1_PART2;
+ uiWriteOffsetWithinPart = 0;
+ }
+
+ if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) {
+ eISOWritePart = ISO_IMAGE1_PART3;
+ uiWriteOffsetWithinPart = 0;
+ }
+ }
+
+ Status = BcmFlash2xBulkRead(Adapter,
+ (PUINT)Buff,
+ eISOReadPart,
+ uiReadOffsetWithinPart,
+ Adapter->uiSectorSize);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart);
+ break;
+ }
+
+ if (IsThisHeaderSector == TRUE) {
+ /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
+ memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);
+
+ for (i = 0; i < MAX_RW_SIZE; i++)
+ *(Buff + sigOffset + i) = 0xFF;
+ }
+ Adapter->bHeaderChangeAllowed = TRUE;
+ Status = BcmFlash2xBulkWrite(Adapter,
+ (PUINT)Buff,
+ eISOWritePart,
+ uiWriteOffsetWithinPart,
+ Adapter->uiSectorSize,
+ TRUE);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart);
+ break;
+ }
+
+ Adapter->bHeaderChangeAllowed = false;
+ if (IsThisHeaderSector == TRUE) {
+ WriteToFlashWithoutSectorErase(Adapter,
+ SigBuff,
+ eISOWritePart,
+ sigOffset,
+ MAX_RW_SIZE);
+
+ IsThisHeaderSector = false;
+ }
+
+ /* subtracting the written Data */
+ uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
+ }
+ }
+out:
+ kfree(Buff);
+
+ return Status;
+}
+
+/*
+ * BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section.
+ * It will corrupt the sig, if Section is writable, by making first bytes as zero.
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @eFlash2xSectionVal :- Flash section val which has header
+ *
+ * Return Value :-
+ * Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS
+ * Failure :-Return negative error code
+ */
+
+int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
+{
+ int Status = STATUS_SUCCESS;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Value :%x\n", eFlash2xSectionVal);
+
+ if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) {
+ Status = CorruptDSDSig(Adapter, eFlash2xSectionVal);
+ } else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) {
+ Status = CorruptISOSig(Adapter, eFlash2xSectionVal);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given Section <%d>does not have Header", eFlash2xSectionVal);
+ return STATUS_SUCCESS;
+ }
+ return Status;
+}
+
+/*
+ *BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has
+ * header and Write Permission.
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @eFlashSectionVal :- Flash section val which has header
+ *
+ * Return Value :-
+ * Success :- If Section is present and writable write the sig and return STATUS_SUCCESS
+ * Failure :-Return negative error code
+ */
+
+int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal)
+{
+ unsigned int uiSignature = 0;
+ unsigned int uiOffset = 0;
+
+ /* struct bcm_dsd_header dsdHeader = {0}; */
+ if (Adapter->bSigCorrupted == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n");
+ return STATUS_SUCCESS;
+ }
+
+ if (Adapter->bAllDSDWriteAllow == false) {
+ if (IsSectionWritable(Adapter, eFlashSectionVal) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature");
+ return SECTOR_IS_NOT_WRITABLE;
+ }
+ }
+
+ if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) {
+ uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER);
+ uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader;
+
+ uiOffset += FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber);
+
+ if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Corrupted Pattern is not there. Hence won't write sig");
+ return STATUS_FAILURE;
+ }
+ } else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) {
+ uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER);
+ /* uiOffset = 0; */
+ uiOffset = FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber);
+ if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig");
+ return STATUS_FAILURE;
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal);
+ return STATUS_FAILURE;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature");
+
+ Adapter->bHeaderChangeAllowed = TRUE;
+ Adapter->bSigCorrupted = false;
+ BcmFlash2xBulkWrite(Adapter, &uiSignature, eFlashSectionVal, uiOffset, SIGNATURE_SIZE, TRUE);
+ Adapter->bHeaderChangeAllowed = false;
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write.
+ * if requested Bytes goes beyond the Requested section, it reports error.
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @psFlash2xReadWrite :-Flash2x Read/write structure pointer
+ *
+ * Return values:-Return TRUE is request is valid else false.
+ */
+
+int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite)
+{
+ unsigned int uiNumOfBytes = 0;
+ unsigned int uiSectStartOffset = 0;
+ unsigned int uiSectEndOffset = 0;
+
+ uiNumOfBytes = psFlash2xReadWrite->numOfBytes;
+
+ if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exist in Flash", psFlash2xReadWrite->Section);
+ return false;
+ }
+ uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section);
+ if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) {
+ if (psFlash2xReadWrite->Section == ISO_IMAGE1) {
+ uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1) -
+ BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) +
+ BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART2) -
+ BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART2) +
+ BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART3) -
+ BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART3);
+ } else if (psFlash2xReadWrite->Section == ISO_IMAGE2) {
+ uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2) -
+ BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2) +
+ BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART2) -
+ BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART2) +
+ BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART3) -
+ BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3);
+ }
+
+ /* since this uiSectEndoffset is the size of iso Image. hence for calculating the virtual endoffset
+ * it should be added in startoffset. so that check done in last of this function can be valued.
+ */
+ uiSectEndOffset = uiSectStartOffset + uiSectEndOffset;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset);
+ } else
+ uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, psFlash2xReadWrite->Section);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset);
+
+ /* psFlash2xReadWrite->offset and uiNumOfBytes are user controlled and can lead to integer overflows */
+ if (psFlash2xReadWrite->offset > uiSectEndOffset) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request....");
+ return false;
+ }
+ if (uiNumOfBytes > uiSectEndOffset) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request....");
+ return false;
+ }
+ /* Checking the boundary condition */
+ if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset)
+ return TRUE;
+ else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request....");
+ return false;
+ }
+}
+
+/*
+ * IsFlash2x :- check for Flash 2.x
+ * Adapater :- Bcm Driver Private Data Structure
+ *
+ * Return value:-
+ * return TRUE if flah2.x of hgher version else return false.
+ */
+
+int IsFlash2x(struct bcm_mini_adapter *Adapter)
+{
+ if (Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER)
+ return TRUE;
+ else
+ return false;
+}
+
+/*
+ * GetFlashBaseAddr :- Calculate the Flash Base address
+ * @Adapater :- Bcm Driver Private Data Structure
+ *
+ * Return Value:-
+ * Success :- Base Address of the Flash
+ */
+
+static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter)
+{
+ unsigned int uiBaseAddr = 0;
+
+ if (Adapter->bDDRInitDone) {
+ /*
+ * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
+ * In case of Raw Read... use the default value
+ */
+ if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == false) &&
+ !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
+ uiBaseAddr = Adapter->uiFlashBaseAdd;
+ else
+ uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT;
+ } else {
+ /*
+ * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
+ * In case of Raw Read... use the default value
+ */
+ if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == false) &&
+ !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
+ uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
+ else
+ uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
+ }
+
+ return uiBaseAddr;
+}
+
+/*
+ * BcmCopySection :- This API is used to copy the One section in another. Both section should
+ * be contiuous and of same size. Hence this Will not be applicabe to copy ISO.
+ *
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @SrcSection :- Source section From where data has to be copied
+ * @DstSection :- Destination section to which data has to be copied
+ * @offset :- Offset from/to where data has to be copied from one section to another.
+ * @numOfBytes :- number of byes that has to be copyed from one section to another at given offset.
+ * in case of numofBytes equal zero complete section will be copied.
+ * Return Values-
+ * Success : Return STATUS_SUCCESS
+ * Faillure :- return negative error code
+ */
+
+int BcmCopySection(struct bcm_mini_adapter *Adapter,
+ enum bcm_flash2x_section_val SrcSection,
+ enum bcm_flash2x_section_val DstSection,
+ unsigned int offset,
+ unsigned int numOfBytes)
+{
+ unsigned int BuffSize = 0;
+ unsigned int BytesToBeCopied = 0;
+ PUCHAR pBuff = NULL;
+ int Status = STATUS_SUCCESS;
+
+ if (SrcSection == DstSection) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source and Destination should be different ...try again");
+ return -EINVAL;
+ }
+
+ if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source should be DSD subsection");
+ return -EINVAL;
+ }
+
+ if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destination should be DSD subsection");
+ return -EINVAL;
+ }
+
+ /* if offset zero means have to copy complete secton */
+ if (numOfBytes == 0) {
+ numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection)
+ - BcmGetSectionValStartOffset(Adapter, SrcSection);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Section Size :0x%x", numOfBytes);
+ }
+
+ if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, SrcSection)
+ - BcmGetSectionValStartOffset(Adapter, SrcSection)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " Input parameters going beyond the section offS: %x numB: %x of Source Section\n",
+ offset, numOfBytes);
+ return -EINVAL;
+ }
+
+ if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, DstSection)
+ - BcmGetSectionValStartOffset(Adapter, DstSection)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Input parameters going beyond the section offS: %x numB: %x of Destination Section\n",
+ offset, numOfBytes);
+ return -EINVAL;
+ }
+
+ if (numOfBytes > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = numOfBytes;
+
+ pBuff = kzalloc(BuffSize, GFP_KERNEL);
+ if (!pBuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. ");
+ return -ENOMEM;
+ }
+
+ BytesToBeCopied = Adapter->uiSectorSize;
+ if (offset % Adapter->uiSectorSize)
+ BytesToBeCopied = Adapter->uiSectorSize - (offset % Adapter->uiSectorSize);
+ if (BytesToBeCopied > numOfBytes)
+ BytesToBeCopied = numOfBytes;
+
+ Adapter->bHeaderChangeAllowed = TRUE;
+
+ do {
+ Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset, BytesToBeCopied);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied);
+ break;
+ }
+ Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, false);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied);
+ break;
+ }
+ offset = offset + BytesToBeCopied;
+ numOfBytes = numOfBytes - BytesToBeCopied;
+ if (numOfBytes) {
+ if (numOfBytes > Adapter->uiSectorSize)
+ BytesToBeCopied = Adapter->uiSectorSize;
+ else
+ BytesToBeCopied = numOfBytes;
+ }
+ } while (numOfBytes > 0);
+
+ kfree(pBuff);
+ Adapter->bHeaderChangeAllowed = false;
+
+ return Status;
+}
+
+/*
+ * SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write
+ * @Adapater :- Bcm Driver Private Data Structure
+ * @pBuff :- Data buffer that has to be written in sector having the header map.
+ * @uiOffset :- Flash offset that has to be written.
+ *
+ * Return value :-
+ * Success :- On success return STATUS_SUCCESS
+ * Faillure :- Return negative error code
+ */
+
+static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiOffset)
+{
+ unsigned int offsetToProtect = 0, HeaderSizeToProtect = 0;
+ bool bHasHeader = false;
+ PUCHAR pTempBuff = NULL;
+ unsigned int uiSectAlignAddr = 0;
+ unsigned int sig = 0;
+
+ /* making the offset sector aligned */
+ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
+
+ if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) ||
+ (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) ||
+ (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) {
+ /* offset from the sector boundary having the header map */
+ offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize;
+ HeaderSizeToProtect = sizeof(struct bcm_dsd_header);
+ bHasHeader = TRUE;
+ }
+
+ if (uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) ||
+ uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) {
+ offsetToProtect = 0;
+ HeaderSizeToProtect = sizeof(struct bcm_iso_header);
+ bHasHeader = TRUE;
+ }
+ /* If Header is present overwrite passed buffer with this */
+ if (bHasHeader && (Adapter->bHeaderChangeAllowed == false)) {
+ pTempBuff = kzalloc(HeaderSizeToProtect, GFP_KERNEL);
+ if (!pTempBuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed");
+ return -ENOMEM;
+ }
+ /* Read header */
+ BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, (uiSectAlignAddr + offsetToProtect), HeaderSizeToProtect);
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pTempBuff, HeaderSizeToProtect);
+ /* Replace Buffer content with Header */
+ memcpy(pBuff + offsetToProtect, pTempBuff, HeaderSizeToProtect);
+
+ kfree(pTempBuff);
+ }
+ if (bHasHeader && Adapter->bSigCorrupted) {
+ sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber)));
+ sig = ntohl(sig);
+ if ((sig & 0xFF000000) != CORRUPTED_PATTERN) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore");
+ Adapter->bSigCorrupted = false;
+ return STATUS_SUCCESS;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Corrupted sig is :%X", sig);
+ *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber))) = htonl(DSD_IMAGE_MAGIC_NUMBER);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature in Header Write only");
+ Adapter->bSigCorrupted = false;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * BcmDoChipSelect : This will selcet the appropriate chip for writing.
+ * @Adapater :- Bcm Driver Private Data Structure
+ *
+ * OutPut:-
+ * Select the Appropriate chip and retrn status Success
+ */
+static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset)
+{
+ unsigned int FlashConfig = 0;
+ int ChipNum = 0;
+ unsigned int GPIOConfig = 0;
+ unsigned int PartNum = 0;
+
+ ChipNum = offset / FLASH_PART_SIZE;
+
+ /*
+ * Chip Select mapping to enable flash0.
+ * To select flash 0, we have to OR with (0<<12).
+ * ORing 0 will have no impact so not doing that part.
+ * In future if Chip select value changes from 0 to non zero,
+ * That needs be taken care with backward comaptibility. No worries for now.
+ */
+
+ /*
+ * SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured
+ * if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken)
+ * Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from
+ * power down modes (Idle mode/shutdown mode), the values in the register will be different.
+ */
+
+ if (Adapter->SelectedChip == ChipNum)
+ return STATUS_SUCCESS;
+
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); */
+ Adapter->SelectedChip = ChipNum;
+
+ /* bit[13..12] will select the appropriate chip */
+ rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
+ rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
+ {
+ switch (ChipNum) {
+ case 0:
+ PartNum = 0;
+ break;
+ case 1:
+ PartNum = 3;
+ GPIOConfig |= (0x4 << CHIP_SELECT_BIT12);
+ break;
+ case 2:
+ PartNum = 1;
+ GPIOConfig |= (0x1 << CHIP_SELECT_BIT12);
+ break;
+ case 3:
+ PartNum = 2;
+ GPIOConfig |= (0x2 << CHIP_SELECT_BIT12);
+ break;
+ }
+ }
+ /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired,
+ * nothing to do... can return immediately.
+ * ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG.
+ * Even if the chip goes to low power mode, it should wake with values in each register in sync with each other.
+ * These values are not written by host other than during CHIP_SELECT.
+ */
+ if (PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3))
+ return STATUS_SUCCESS;
+
+ /* clearing the bit[13..12] */
+ FlashConfig &= 0xFFFFCFFF;
+ FlashConfig = (FlashConfig | (PartNum<<CHIP_SELECT_BIT12)); /* 00 */
+
+ wrmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
+ udelay(100);
+
+ wrmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
+ udelay(100);
+
+ return STATUS_SUCCESS;
+}
+
+static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd)
+{
+ unsigned int uiDSDsig = 0;
+ /* unsigned int sigoffsetInMap = 0;
+ * struct bcm_dsd_header dsdHeader = {0};
+ */
+
+ /* sigoffsetInMap =(PUCHAR)&(dsdHeader.DSDImageMagicNumber) -(PUCHAR)&dsdHeader; */
+
+ if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for DSDs");
+ return STATUS_FAILURE;
+ }
+ BcmFlash2xBulkRead(Adapter,
+ &uiDSDsig,
+ dsd,
+ Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber),
+ SIGNATURE_SIZE);
+
+ uiDSDsig = ntohl(uiDSDsig);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD SIG :%x", uiDSDsig);
+
+ return uiDSDsig;
+}
+
+static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd)
+{
+ /* unsigned int priOffsetInMap = 0 ; */
+ unsigned int uiDSDPri = STATUS_FAILURE;
+ /* struct bcm_dsd_header dsdHeader = {0};
+ * priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader;
+ */
+ if (IsSectionWritable(Adapter, dsd)) {
+ if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) {
+ BcmFlash2xBulkRead(Adapter,
+ &uiDSDPri,
+ dsd,
+ Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
+ 4);
+
+ uiDSDPri = ntohl(uiDSDPri);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD<%x> Priority :%x", dsd, uiDSDPri);
+ }
+ }
+
+ return uiDSDPri;
+}
+
+static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter)
+{
+ int DSDHighestPri = STATUS_FAILURE;
+ int DsdPri = 0;
+ enum bcm_flash2x_section_val HighestPriDSD = 0;
+
+ if (IsSectionWritable(Adapter, DSD2)) {
+ DSDHighestPri = ReadDSDPriority(Adapter, DSD2);
+ HighestPriDSD = DSD2;
+ }
+
+ if (IsSectionWritable(Adapter, DSD1)) {
+ DsdPri = ReadDSDPriority(Adapter, DSD1);
+ if (DSDHighestPri < DsdPri) {
+ DSDHighestPri = DsdPri;
+ HighestPriDSD = DSD1;
+ }
+ }
+
+ if (IsSectionWritable(Adapter, DSD0)) {
+ DsdPri = ReadDSDPriority(Adapter, DSD0);
+ if (DSDHighestPri < DsdPri) {
+ DSDHighestPri = DsdPri;
+ HighestPriDSD = DSD0;
+ }
+ }
+ if (HighestPriDSD)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest DSD :%x , and its Pri :%x", HighestPriDSD, DSDHighestPri);
+
+ return HighestPriDSD;
+}
+
+static int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
+{
+ unsigned int uiISOsig = 0;
+ /* unsigned int sigoffsetInMap = 0;
+ * struct bcm_iso_header ISOHeader = {0};
+ * sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader;
+ */
+ if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for ISOs");
+ return STATUS_FAILURE;
+ }
+ BcmFlash2xBulkRead(Adapter,
+ &uiISOsig,
+ iso,
+ 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber),
+ SIGNATURE_SIZE);
+
+ uiISOsig = ntohl(uiISOsig);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO SIG :%x", uiISOsig);
+
+ return uiISOsig;
+}
+
+static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
+{
+ unsigned int ISOPri = STATUS_FAILURE;
+ if (IsSectionWritable(Adapter, iso)) {
+ if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) {
+ BcmFlash2xBulkRead(Adapter,
+ &ISOPri,
+ iso,
+ 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority),
+ 4);
+
+ ISOPri = ntohl(ISOPri);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO<%x> Priority :%x", iso, ISOPri);
+ }
+ }
+
+ return ISOPri;
+}
+
+static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter)
+{
+ int ISOHighestPri = STATUS_FAILURE;
+ int ISOPri = 0;
+ enum bcm_flash2x_section_val HighestPriISO = NO_SECTION_VAL;
+
+ if (IsSectionWritable(Adapter, ISO_IMAGE2)) {
+ ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2);
+ HighestPriISO = ISO_IMAGE2;
+ }
+
+ if (IsSectionWritable(Adapter, ISO_IMAGE1)) {
+ ISOPri = ReadISOPriority(Adapter, ISO_IMAGE1);
+ if (ISOHighestPri < ISOPri) {
+ ISOHighestPri = ISOPri;
+ HighestPriISO = ISO_IMAGE1;
+ }
+ }
+ if (HighestPriISO)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest ISO :%x and its Pri :%x", HighestPriISO, ISOHighestPri);
+
+ return HighestPriISO;
+}
+
+static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
+ PUINT pBuff,
+ enum bcm_flash2x_section_val eFlash2xSectionVal,
+ unsigned int uiOffset,
+ unsigned int uiNumBytes)
+{
+ #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
+ unsigned int uiTemp = 0, value = 0;
+ unsigned int i = 0;
+ unsigned int uiPartOffset = 0;
+ #endif
+ unsigned int uiStartOffset = 0;
+ /* Adding section start address */
+ int Status = STATUS_SUCCESS;
+ PUCHAR pcBuff = (PUCHAR)pBuff;
+
+ if (uiNumBytes % Adapter->ulFlashWriteSize) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes);
+ return STATUS_FAILURE;
+ }
+
+ uiStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
+
+ if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
+ return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes);
+
+ uiOffset = uiOffset + uiStartOffset;
+
+ #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
+ Status = bcmflash_raw_writenoerase((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), pcBuff, uiNumBytes);
+ #else
+ rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ value = 0;
+ wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
+
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ BcmDoChipSelect(Adapter, uiOffset);
+ uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
+
+ for (i = 0; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
+ if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT)
+ Status = flashByteWrite(Adapter, uiPartOffset, pcBuff);
+ else
+ Status = flashWrite(Adapter, uiPartOffset, pcBuff);
+
+ if (Status != STATUS_SUCCESS)
+ break;
+
+ pcBuff = pcBuff + Adapter->ulFlashWriteSize;
+ uiPartOffset = uiPartOffset + Adapter->ulFlashWriteSize;
+ }
+ wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
+ Adapter->SelectedChip = RESET_CHIP_SELECT;
+ #endif
+
+ return Status;
+}
+
+bool IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
+{
+ bool SectionPresent = false;
+
+ switch (section) {
+ case ISO_IMAGE1:
+ if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) &&
+ (IsNonCDLessDevice(Adapter) == false))
+ SectionPresent = TRUE;
+ break;
+ case ISO_IMAGE2:
+ if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) &&
+ (IsNonCDLessDevice(Adapter) == false))
+ SectionPresent = TRUE;
+ break;
+ case DSD0:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case DSD1:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case DSD2:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case VSA0:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case VSA1:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case VSA2:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case SCSI:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ case CONTROL_SECTION:
+ if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS)
+ SectionPresent = TRUE;
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
+ SectionPresent = false;
+ }
+
+ return SectionPresent;
+}
+
+static int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section)
+{
+ int offset = STATUS_FAILURE;
+ int Status = false;
+
+ if (IsSectionExistInFlash(Adapter, Section) == false) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exist", Section);
+ return false;
+ }
+
+ offset = BcmGetSectionValStartOffset(Adapter, Section);
+ if (offset == INVALID_OFFSET) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exist", Section);
+ return false;
+ }
+
+ if (IsSectionExistInVendorInfo(Adapter, Section))
+ return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO);
+
+ Status = IsOffsetWritable(Adapter, offset);
+ return Status;
+}
+
+static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
+{
+ PUCHAR pBuff = NULL;
+ unsigned int sig = 0;
+ unsigned int uiOffset = 0;
+ unsigned int BlockStatus = 0;
+ unsigned int uiSectAlignAddr = 0;
+
+ Adapter->bSigCorrupted = false;
+ if (Adapter->bAllDSDWriteAllow == false) {
+ if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
+ return SECTOR_IS_NOT_WRITABLE;
+ }
+ }
+
+ pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
+ if (!pBuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
+ return -ENOMEM;
+ }
+
+ uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header);
+ uiOffset -= MAX_RW_SIZE;
+
+ BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE);
+
+ sig = *((PUINT)(pBuff + 12));
+ sig = ntohl(sig);
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE);
+ /* Now corrupting the sig by corrupting 4th last Byte. */
+ *(pBuff + 12) = 0;
+
+ if (sig == DSD_IMAGE_MAGIC_NUMBER) {
+ Adapter->bSigCorrupted = TRUE;
+ if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) {
+ uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
+ BlockStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize);
+
+ WriteToFlashWithoutSectorErase(Adapter, (PUINT)(pBuff + 12), eFlash2xSectionVal,
+ (uiOffset + 12), BYTE_WRITE_SUPPORT);
+ if (BlockStatus) {
+ BcmRestoreBlockProtectStatus(Adapter, BlockStatus);
+ BlockStatus = 0;
+ }
+ } else {
+ WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal,
+ uiOffset, MAX_RW_SIZE);
+ }
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header");
+ kfree(pBuff);
+
+ return STATUS_FAILURE;
+ }
+
+ kfree(pBuff);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature");
+
+ return STATUS_SUCCESS;
+}
+
+static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
+{
+ PUCHAR pBuff = NULL;
+ unsigned int sig = 0;
+ unsigned int uiOffset = 0;
+
+ Adapter->bSigCorrupted = false;
+
+ if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
+ return SECTOR_IS_NOT_WRITABLE;
+ }
+
+ pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
+ if (!pBuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
+ return -ENOMEM;
+ }
+
+ uiOffset = 0;
+
+ BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE);
+
+ sig = *((PUINT)pBuff);
+ sig = ntohl(sig);
+
+ /* corrupt signature */
+ *pBuff = 0;
+
+ if (sig == ISO_IMAGE_MAGIC_NUMBER) {
+ Adapter->bSigCorrupted = TRUE;
+ WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal,
+ uiOffset, Adapter->ulFlashWriteSize);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header");
+ kfree(pBuff);
+
+ return STATUS_FAILURE;
+ }
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature");
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE);
+
+ kfree(pBuff);
+ return STATUS_SUCCESS;
+}
+
+bool IsNonCDLessDevice(struct bcm_mini_adapter *Adapter)
+{
+ if (Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG)
+ return TRUE;
+ else
+ return false;
+}
diff --git a/drivers/staging/bcm/nvm.h b/drivers/staging/bcm/nvm.h
new file mode 100644
index 00000000000..e765cca5d96
--- /dev/null
+++ b/drivers/staging/bcm/nvm.h
@@ -0,0 +1,286 @@
+/***************************************************************************************
+ *
+ * Copyright (c) Beceem Communications Inc.
+ *
+ * Module Name:
+ * NVM.h
+ *
+ * Abstract:
+ * This file has the prototypes,preprocessors and definitions various NVM libraries.
+ *
+ *
+ * Revision History:
+ * Who When What
+ * -------- -------- ----------------------------------------------
+ * Name Date Created/reviewed/modified
+ *
+ * Notes:
+ *
+ ****************************************************************************************/
+
+#ifndef _NVM_H_
+#define _NVM_H_
+
+struct bcm_flash_cs_info {
+ u32 MagicNumber;
+ /* let the magic number be 0xBECE-F1A5 - F1A5 for "flas-h" */
+ u32 FlashLayoutVersion;
+ u32 ISOImageVersion;
+ u32 SCSIFirmwareVersion;
+ u32 OffsetFromZeroForPart1ISOImage;
+ u32 OffsetFromZeroForScsiFirmware;
+ u32 SizeOfScsiFirmware;
+ u32 OffsetFromZeroForPart2ISOImage;
+ u32 OffsetFromZeroForCalibrationStart;
+ u32 OffsetFromZeroForCalibrationEnd;
+ u32 OffsetFromZeroForVSAStart;
+ u32 OffsetFromZeroForVSAEnd;
+ u32 OffsetFromZeroForControlSectionStart;
+ u32 OffsetFromZeroForControlSectionData;
+ u32 CDLessInactivityTimeout;
+ u32 NewImageSignature;
+ u32 FlashSectorSizeSig;
+ u32 FlashSectorSize;
+ u32 FlashWriteSupportSize;
+ u32 TotalFlashSize;
+ u32 FlashBaseAddr;
+ u32 FlashPartMaxSize;
+ u32 IsCDLessDeviceBootSig;
+ /* MSC Timeout after reset to switch from MSC to NW Mode */
+ u32 MassStorageTimeout;
+};
+
+#define FLASH2X_TOTAL_SIZE (64 * 1024 * 1024)
+#define DEFAULT_SECTOR_SIZE (64 * 1024)
+
+struct bcm_flash2x_cs_info {
+ /* magic number as 0xBECE-F1A5 - F1A5 for "flas-h" */
+ u32 MagicNumber;
+ u32 FlashLayoutVersion;
+ u32 ISOImageVersion;
+ u32 SCSIFirmwareVersion;
+ u32 OffsetFromZeroForPart1ISOImage;
+ u32 OffsetFromZeroForScsiFirmware;
+ u32 SizeOfScsiFirmware;
+ u32 OffsetFromZeroForPart2ISOImage;
+ u32 OffsetFromZeroForDSDStart;
+ u32 OffsetFromZeroForDSDEnd;
+ u32 OffsetFromZeroForVSAStart;
+ u32 OffsetFromZeroForVSAEnd;
+ u32 OffsetFromZeroForControlSectionStart;
+ u32 OffsetFromZeroForControlSectionData;
+ /* NO Data Activity timeout to switch from MSC to NW Mode */
+ u32 CDLessInactivityTimeout;
+ u32 NewImageSignature;
+ u32 FlashSectorSizeSig;
+ u32 FlashSectorSize;
+ u32 FlashWriteSupportSize;
+ u32 TotalFlashSize;
+ u32 FlashBaseAddr;
+ u32 FlashPartMaxSize;
+ u32 IsCDLessDeviceBootSig;
+ /* MSC Timeout after reset to switch from MSC to NW Mode */
+ u32 MassStorageTimeout;
+ /* Flash Map 2.0 Field */
+ u32 OffsetISOImage1Part1Start;
+ u32 OffsetISOImage1Part1End;
+ u32 OffsetISOImage1Part2Start;
+ u32 OffsetISOImage1Part2End;
+ u32 OffsetISOImage1Part3Start;
+ u32 OffsetISOImage1Part3End;
+ u32 OffsetISOImage2Part1Start;
+ u32 OffsetISOImage2Part1End;
+ u32 OffsetISOImage2Part2Start;
+ u32 OffsetISOImage2Part2End;
+ u32 OffsetISOImage2Part3Start;
+ u32 OffsetISOImage2Part3End;
+ /* DSD Header offset from start of DSD */
+ u32 OffsetFromDSDStartForDSDHeader;
+ u32 OffsetFromZeroForDSD1Start;
+ u32 OffsetFromZeroForDSD1End;
+ u32 OffsetFromZeroForDSD2Start;
+ u32 OffsetFromZeroForDSD2End;
+ u32 OffsetFromZeroForVSA1Start;
+ u32 OffsetFromZeroForVSA1End;
+ u32 OffsetFromZeroForVSA2Start;
+ u32 OffsetFromZeroForVSA2End;
+ /*
+ * ACCESS_BITS_PER_SECTOR 2
+ * ACCESS_RW 0
+ * ACCESS_RO 1
+ * ACCESS_RESVD 2
+ * ACCESS_RESVD 3
+ */
+ u32 SectorAccessBitMap[FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)];
+ /* All expansions to the control data structure should add here */
+};
+
+struct bcm_vendor_section_info {
+ u32 OffsetFromZeroForSectionStart;
+ u32 OffsetFromZeroForSectionEnd;
+ u32 AccessFlags;
+ u32 Reserved[16];
+};
+
+struct bcm_flash2x_vendor_info {
+ struct bcm_vendor_section_info VendorSection[TOTAL_SECTIONS];
+ u32 Reserved[16];
+};
+
+struct bcm_dsd_header {
+ u32 DSDImageSize;
+ u32 DSDImageCRC;
+ u32 DSDImagePriority;
+ /* We should not consider right now. Reading reserve is worthless. */
+ u32 Reserved[252]; /* Resvd for DSD Header */
+ u32 DSDImageMagicNumber;
+};
+
+struct bcm_iso_header {
+ u32 ISOImageMagicNumber;
+ u32 ISOImageSize;
+ u32 ISOImageCRC;
+ u32 ISOImagePriority;
+ /* We should not consider right now. Reading reserve is worthless. */
+ u32 Reserved[60]; /* Resvd for ISO Header extension */
+};
+
+#define EEPROM_BEGIN_CIS (0)
+#define EEPROM_BEGIN_NON_CIS (0x200)
+#define EEPROM_END (0x2000)
+#define INIT_PARAMS_SIGNATURE (0x95a7a597)
+#define MAX_INIT_PARAMS_LENGTH (2048)
+#define MAC_ADDRESS_OFFSET 0x200
+
+#define INIT_PARAMS_1_SIGNATURE_ADDRESS EEPROM_BEGIN_NON_CIS
+#define INIT_PARAMS_1_DATA_ADDRESS (INIT_PARAMS_1_SIGNATURE_ADDRESS+16)
+#define INIT_PARAMS_1_MACADDRESS_ADDRESS (MAC_ADDRESS_OFFSET)
+#define INIT_PARAMS_1_LENGTH_ADDRESS (INIT_PARAMS_1_SIGNATURE_ADDRESS+4)
+
+#define INIT_PARAMS_2_SIGNATURE_ADDRESS (EEPROM_BEGIN_NON_CIS + 2048 + 16)
+#define INIT_PARAMS_2_DATA_ADDRESS (INIT_PARAMS_2_SIGNATURE_ADDRESS + 16)
+#define INIT_PARAMS_2_MACADDRESS_ADDRESS (INIT_PARAMS_2_SIGNATURE_ADDRESS + 8)
+#define INIT_PARAMS_2_LENGTH_ADDRESS (INIT_PARAMS_2_SIGNATURE_ADDRESS + 4)
+
+#define EEPROM_SPI_DEV_CONFIG_REG 0x0F003000
+#define EEPROM_SPI_Q_STATUS1_REG 0x0F003004
+#define EEPROM_SPI_Q_STATUS1_MASK_REG 0x0F00300C
+
+#define EEPROM_SPI_Q_STATUS_REG 0x0F003008
+#define EEPROM_CMDQ_SPI_REG 0x0F003018
+#define EEPROM_WRITE_DATAQ_REG 0x0F00301C
+#define EEPROM_READ_DATAQ_REG 0x0F003020
+#define SPI_FLUSH_REG 0x0F00304C
+
+#define EEPROM_WRITE_ENABLE 0x06000000
+#define EEPROM_READ_STATUS_REGISTER 0x05000000
+#define EEPROM_16_BYTE_PAGE_WRITE 0xFA000000
+#define EEPROM_WRITE_QUEUE_EMPTY 0x00001000
+#define EEPROM_WRITE_QUEUE_AVAIL 0x00002000
+#define EEPROM_WRITE_QUEUE_FULL 0x00004000
+#define EEPROM_16_BYTE_PAGE_READ 0xFB000000
+#define EEPROM_4_BYTE_PAGE_READ 0x3B000000
+
+#define EEPROM_CMD_QUEUE_FLUSH 0x00000001
+#define EEPROM_WRITE_QUEUE_FLUSH 0x00000002
+#define EEPROM_READ_QUEUE_FLUSH 0x00000004
+#define EEPROM_ETH_QUEUE_FLUSH 0x00000008
+#define EEPROM_ALL_QUEUE_FLUSH 0x0000000f
+#define EEPROM_READ_ENABLE 0x06000000
+#define EEPROM_16_BYTE_PAGE_WRITE 0xFA000000
+#define EEPROM_READ_DATA_FULL 0x00000010
+#define EEPROM_READ_DATA_AVAIL 0x00000020
+#define EEPROM_READ_QUEUE_EMPTY 0x00000002
+#define EEPROM_CMD_QUEUE_EMPTY 0x00000100
+#define EEPROM_CMD_QUEUE_AVAIL 0x00000200
+#define EEPROM_CMD_QUEUE_FULL 0x00000400
+
+/* Most EEPROM status register bit 0 indicates if the EEPROM is busy
+ * with a write if set 1. See the details of the EEPROM Status Register
+ * in the EEPROM data sheet.
+ */
+#define EEPROM_STATUS_REG_WRITE_BUSY 0x00000001
+
+/* We will have 1 mSec for every RETRIES_PER_DELAY count and have a max attempts of MAX_EEPROM_RETRIES
+ * This will give us 80 mSec minimum of delay = 80mSecs
+ */
+#define MAX_EEPROM_RETRIES 80
+#define RETRIES_PER_DELAY 64
+#define MAX_RW_SIZE 0x10
+#define MAX_READ_SIZE 0x10
+#define MAX_SECTOR_SIZE (512 * 1024)
+#define MIN_SECTOR_SIZE (1024)
+#define FLASH_SECTOR_SIZE_OFFSET 0xEFFFC
+#define FLASH_SECTOR_SIZE_SIG_OFFSET 0xEFFF8
+#define FLASH_SECTOR_SIZE_SIG 0xCAFEBABE
+#define FLASH_CS_INFO_START_ADDR 0xFF0000
+#define FLASH_CONTROL_STRUCT_SIGNATURE 0xBECEF1A5
+#define SCSI_FIRMWARE_MAJOR_VERSION 0x1
+#define SCSI_FIRMWARE_MINOR_VERSION 0x5
+#define BYTE_WRITE_SUPPORT 0x1
+#define FLASH_AUTO_INIT_BASE_ADDR 0xF00000
+#define FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT 0x1C000000
+#define FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT 0x1F000000
+#define FLASH_CONTIGIOUS_START_ADDR_BCS350 0x08000000
+#define FLASH_CONTIGIOUS_END_ADDR_BCS350 0x08FFFFFF
+#define FLASH_SIZE_ADDR 0xFFFFEC
+#define FLASH_SPI_CMDQ_REG 0xAF003040
+#define FLASH_SPI_WRITEQ_REG 0xAF003044
+#define FLASH_SPI_READQ_REG 0xAF003048
+#define FLASH_CONFIG_REG 0xAF003050
+#define FLASH_GPIO_CONFIG_REG 0xAF000030
+#define FLASH_CMD_WRITE_ENABLE 0x06
+#define FLASH_CMD_READ_ENABLE 0x03
+#define FLASH_CMD_RESET_WRITE_ENABLE 0x04
+#define FLASH_CMD_STATUS_REG_READ 0x05
+#define FLASH_CMD_STATUS_REG_WRITE 0x01
+#define FLASH_CMD_READ_ID 0x9F
+#define PAD_SELECT_REGISTER 0xAF000410
+#define FLASH_PART_SST25VF080B 0xBF258E
+#define EEPROM_CAL_DATA_INTERNAL_LOC 0xbFB00008
+#define EEPROM_CALPARAM_START 0x200
+#define EEPROM_SIZE_OFFSET 524
+
+/* As Read/Write time vaires from 1.5 to 3.0 ms.
+ * so After Ignoring the rdm/wrm time(that is dependent on many factor like interface etc.),
+ * here time calculated meets the worst case delay, 3.0 ms
+ */
+#define MAX_FLASH_RETRIES 4
+#define FLASH_PER_RETRIES_DELAY 16
+#define EEPROM_MAX_CAL_AREA_SIZE 0xF0000
+#define BECM ntohl(0x4245434d)
+#define FLASH_2X_MAJOR_NUMBER 0x2
+#define DSD_IMAGE_MAGIC_NUMBER 0xBECE0D5D
+#define ISO_IMAGE_MAGIC_NUMBER 0xBECE0150
+#define NON_CDLESS_DEVICE_BOOT_SIG 0xBECEB007
+
+#define MINOR_VERSION(x) ((x >> 16) & 0xFFFF)
+#define MAJOR_VERSION(x) (x & 0xFFFF)
+
+#define CORRUPTED_PATTERN 0x0
+#define UNINIT_PTR_IN_CS 0xBBBBDDDD
+#define VENDOR_PTR_IN_CS 0xAAAACCCC
+#define FLASH2X_SECTION_PRESENT (1 << 0)
+#define FLASH2X_SECTION_VALID (1 << 1)
+#define FLASH2X_SECTION_RO (1 << 2)
+#define FLASH2X_SECTION_ACT (1 << 3)
+#define SECTOR_IS_NOT_WRITABLE STATUS_FAILURE
+#define INVALID_OFFSET STATUS_FAILURE
+#define INVALID_SECTION STATUS_FAILURE
+#define SECTOR_1K 1024
+#define SECTOR_64K (64 * SECTOR_1K)
+#define SECTOR_128K (2 * SECTOR_64K)
+#define SECTOR_256k (2 * SECTOR_128K)
+#define SECTOR_512K (2 * SECTOR_256k)
+#define FLASH_PART_SIZE (16 * 1024 * 1024)
+#define RESET_CHIP_SELECT -1
+#define CHIP_SELECT_BIT12 12
+#define SECTOR_READWRITE_PERMISSION 0
+#define SECTOR_READONLY 1
+#define SIGNATURE_SIZE 4
+#define DEFAULT_BUFF_SIZE 0x10000
+
+#define FIELD_OFFSET_IN_HEADER(HeaderPointer, Field) ((u8 *)&((HeaderPointer)(NULL))->Field - (u8 *)(NULL))
+
+#endif
+
diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c
new file mode 100644
index 00000000000..d518c4217f1
--- /dev/null
+++ b/drivers/staging/bcm/sort.c
@@ -0,0 +1,52 @@
+#include "headers.h"
+#include <linux/sort.h>
+
+/*
+ * File Name: sort.c
+ *
+ * Author: Beceem Communications Pvt. Ltd
+ *
+ * Abstract: This file contains the routines sorting the classification rules.
+ *
+ * Copyright (c) 2007 Beceem Communications Pvt. Ltd
+ */
+
+static int compare_packet_info(void const *a, void const *b)
+{
+ struct bcm_packet_info const *pa = a;
+ struct bcm_packet_info const *pb = b;
+
+ if (!pa->bValid || !pb->bValid)
+ return 0;
+
+ return pa->u8TrafficPriority - pb->u8TrafficPriority;
+}
+
+VOID SortPackInfo(struct bcm_mini_adapter *Adapter)
+{
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "<=======");
+
+ sort(Adapter->PackInfo, NO_OF_QUEUES, sizeof(struct bcm_packet_info),
+ compare_packet_info, NULL);
+}
+
+static int compare_classifiers(void const *a, void const *b)
+{
+ struct bcm_classifier_rule const *pa = a;
+ struct bcm_classifier_rule const *pb = b;
+
+ if (!pa->bUsed || !pb->bUsed)
+ return 0;
+
+ return pa->u8ClassifierRulePriority - pb->u8ClassifierRulePriority;
+}
+
+VOID SortClassifiers(struct bcm_mini_adapter *Adapter)
+{
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+ DBG_LVL_ALL, "<=======");
+
+ sort(Adapter->astClassifierTable, MAX_CLASSIFIERS,
+ sizeof(struct bcm_classifier_rule), compare_classifiers, NULL);
+}
diff --git a/drivers/staging/bcm/target_params.h b/drivers/staging/bcm/target_params.h
new file mode 100644
index 00000000000..dc45f9ab854
--- /dev/null
+++ b/drivers/staging/bcm/target_params.h
@@ -0,0 +1,57 @@
+#ifndef TARGET_PARAMS_H
+#define TARGET_PARAMS_H
+
+struct bcm_target_params {
+ u32 m_u32CfgVersion;
+ u32 m_u32CenterFrequency;
+ u32 m_u32BandAScan;
+ u32 m_u32BandBScan;
+ u32 m_u32BandCScan;
+ u32 m_u32ErtpsOptions;
+ u32 m_u32PHSEnable;
+ u32 m_u32HoEnable;
+ u32 m_u32HoReserved1;
+ u32 m_u32HoReserved2;
+ u32 m_u32MimoEnable;
+ u32 m_u32SecurityEnable;
+ u32 m_u32PowerSavingModesEnable; /* bit 1: 1 Idlemode enable; bit2: 1 Sleepmode Enable */
+ /* PowerSaving Mode Options:
+ * bit 0 = 1: CPE mode - to keep pcmcia if alive;
+ * bit 1 = 1: CINR reporting in Idlemode Msg
+ * bit 2 = 1: Default PSC Enable in sleepmode
+ */
+ u32 m_u32PowerSavingModeOptions;
+ u32 m_u32ArqEnable;
+ /* From Version #3, the HARQ section renamed as general */
+ u32 m_u32HarqEnable;
+ u32 m_u32EEPROMFlag;
+ /* BINARY TYPE - 4th MSByte: Interface Type - 3rd MSByte: Vendor Type - 2nd MSByte
+ * Unused - LSByte
+ */
+ u32 m_u32Customize;
+ u32 m_u32ConfigBW; /* In Hz */
+ u32 m_u32ShutDownInitThresholdTimer;
+ u32 m_u32RadioParameter;
+ u32 m_u32PhyParameter1;
+ u32 m_u32PhyParameter2;
+ u32 m_u32PhyParameter3;
+ u32 m_u32TestOptions; /* in eval mode only; lower 16bits = basic cid for testing; then bit 16 is test cqich,bit 17 test init rang; bit 18 test periodic rang and bit 19 is test harq ack/nack */
+ u32 m_u32MaxMACDataperDLFrame;
+ u32 m_u32MaxMACDataperULFrame;
+ u32 m_u32Corr2MacFlags;
+ u32 HostDrvrConfig1;
+ u32 HostDrvrConfig2;
+ u32 HostDrvrConfig3;
+ u32 HostDrvrConfig4;
+ u32 HostDrvrConfig5;
+ u32 HostDrvrConfig6;
+ u32 m_u32SegmentedPUSCenable;
+ /* removed SHUT down related 'unused' params from here to sync 4.x and 5.x CFG files..
+ * BAMC Related Parameters
+ * Bit 0-15 Band AMC signaling configuration: Bit 1 = 1 – Enable Band AMC signaling.
+ * bit 16-31 Band AMC Data configuration: Bit 16 = 1 – Band AMC 2x3 support.
+ */
+ u32 m_u32BandAMCEnable;
+};
+
+#endif
diff --git a/drivers/staging/bcm/vendorspecificextn.c b/drivers/staging/bcm/vendorspecificextn.c
new file mode 100644
index 00000000000..2c57a16788c
--- /dev/null
+++ b/drivers/staging/bcm/vendorspecificextn.c
@@ -0,0 +1,142 @@
+#include "headers.h"
+/*
+ * Procedure: vendorextnGetSectionInfo
+ *
+ * Description: Finds the type of NVM used.
+ *
+ * Arguments:
+ * Adapter - ptr to Adapter object instance
+ * pNVMType - ptr to NVM type.
+ * Returns:
+ * STATUS_SUCCESS/STATUS_FAILURE
+ *
+ */
+INT vendorextnGetSectionInfo(PVOID pContext, struct bcm_flash2x_vendor_info *pVendorInfo)
+{
+ return STATUS_FAILURE;
+}
+
+/*
+ * Procedure: vendorextnInit
+ *
+ * Description: Initializing the vendor extension NVM interface
+ *
+ * Arguments:
+ * Adapter - Pointer to MINI Adapter Structure
+ * Returns:
+ * STATUS_SUCCESS/STATUS_FAILURE
+ *
+ *
+ */
+INT vendorextnInit(struct bcm_mini_adapter *Adapter)
+{
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Procedure: vendorextnExit
+ *
+ * Description: Free the resource associated with vendor extension NVM interface
+ *
+ * Arguments:
+ *
+ * Returns:
+ * STATUS_SUCCESS/STATUS_FAILURE
+ *
+ *
+ */
+INT vendorextnExit(struct bcm_mini_adapter *Adapter)
+{
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Procedure: vendorextnIoctl
+ *
+ * Description: execute the vendor extension specific ioctl
+ *
+ * Arguments:
+ * Adapter -Beceem private Adapter Structure
+ * cmd -vendor extension specific Ioctl commad
+ * arg -input parameter sent by vendor
+ *
+ * Returns:
+ * CONTINUE_COMMON_PATH in case it is not meant to be processed by vendor ioctls
+ * STATUS_SUCCESS/STATUS_FAILURE as per the IOCTL return value
+ */
+
+INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg)
+{
+ return CONTINUE_COMMON_PATH;
+}
+
+
+
+/*
+ * Procedure: vendorextnReadSection
+ *
+ * Description: Reads from a section of NVM
+ *
+ * Arguments:
+ * pContext - ptr to Adapter object instance
+ * pBuffer - Read the data from Vendor Area to this buffer
+ * SectionVal - Value of type of Section
+ * Offset - Read from the Offset of the Vendor Section.
+ * numOfBytes - Read numOfBytes from the Vendor section to Buffer
+ *
+ * Returns:
+ * STATUS_SUCCESS/STATUS_FAILURE
+ */
+
+INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
+ UINT offset, UINT numOfBytes)
+{
+ return STATUS_FAILURE;
+}
+
+
+
+/*
+ * Procedure: vendorextnWriteSection
+ *
+ * Description: Write to a Section of NVM
+ *
+ * Arguments:
+ * pContext - ptr to Adapter object instance
+ * pBuffer - Write the data provided in the buffer
+ * SectionVal - Value of type of Section
+ * Offset - Writes to the Offset of the Vendor Section.
+ * numOfBytes - Write num Bytes after reading from pBuffer.
+ * bVerify - the Buffer Written should be verified.
+ *
+ * Returns:
+ * STATUS_SUCCESS/STATUS_FAILURE
+ */
+INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
+ UINT offset, UINT numOfBytes, bool bVerify)
+{
+ return STATUS_FAILURE;
+}
+
+
+
+/*
+ * Procedure: vendorextnWriteSectionWithoutErase
+ *
+ * Description: Write to a Section of NVM without erasing the sector
+ *
+ * Arguments:
+ * pContext - ptr to Adapter object instance
+ * pBuffer - Write the data provided in the buffer
+ * SectionVal - Value of type of Section
+ * Offset - Writes to the Offset of the Vendor Section.
+ * numOfBytes - Write num Bytes after reading from pBuffer.
+ *
+ * Returns:
+ * STATUS_SUCCESS/STATUS_FAILURE
+ */
+INT vendorextnWriteSectionWithoutErase(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
+ UINT offset, UINT numOfBytes)
+{
+ return STATUS_FAILURE;
+}
diff --git a/drivers/staging/bcm/vendorspecificextn.h b/drivers/staging/bcm/vendorspecificextn.h
new file mode 100644
index 00000000000..ff57f057045
--- /dev/null
+++ b/drivers/staging/bcm/vendorspecificextn.h
@@ -0,0 +1,18 @@
+
+#ifndef __VENDOR_EXTN_NVM_H__
+#define __VENDOR_EXTN_NVM_H__
+
+#define CONTINUE_COMMON_PATH 0xFFFF
+
+INT vendorextnGetSectionInfo(PVOID pContext, struct bcm_flash2x_vendor_info *pVendorInfo);
+INT vendorextnExit(struct bcm_mini_adapter *Adapter);
+INT vendorextnInit(struct bcm_mini_adapter *Adapter);
+INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg);
+INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
+ UINT offset, UINT numOfBytes);
+INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
+ UINT offset, UINT numOfBytes, bool bVerify);
+INT vendorextnWriteSectionWithoutErase(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
+ UINT offset, UINT numOfBytes);
+
+#endif /* */